| Line Number |
../DebugInfoTest/example_mips_dbg.ll
BUT NOT
../DebugInfoTest/example_mips.ll
|
Line Number |
../DebugInfoTest/example_mips.ll
BUT NOT
../DebugInfoTest/example_mips_dbg.ll
|
| 1 |
//===- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions -------===// |
1 |
//===- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions -------===// |
| 2 |
// |
2 |
// |
| 3 |
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
3 |
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 |
// See https://llvm.org/LICENSE.txt for license information. |
4 |
// See https://llvm.org/LICENSE.txt for license information. |
| 5 |
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
5 |
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 |
// |
6 |
// |
| 7 |
//===----------------------------------------------------------------------===// |
7 |
//===----------------------------------------------------------------------===// |
| 8 |
|
8 |
|
| 9 |
#include "ARMBaseInstrInfo.h" |
9 |
#include "ARMBaseInstrInfo.h" |
| 10 |
#include "ARMFeatures.h" |
10 |
#include "ARMFeatures.h" |
| 11 |
#include "MCTargetDesc/ARMAddressingModes.h" |
11 |
#include "MCTargetDesc/ARMAddressingModes.h" |
| 12 |
#include "MCTargetDesc/ARMBaseInfo.h" |
12 |
#include "MCTargetDesc/ARMBaseInfo.h" |
| 13 |
#include "MCTargetDesc/ARMInstPrinter.h" |
13 |
#include "MCTargetDesc/ARMInstPrinter.h" |
| 14 |
#include "MCTargetDesc/ARMMCExpr.h" |
14 |
#include "MCTargetDesc/ARMMCExpr.h" |
| 15 |
#include "MCTargetDesc/ARMMCTargetDesc.h" |
15 |
#include "MCTargetDesc/ARMMCTargetDesc.h" |
| 16 |
#include "TargetInfo/ARMTargetInfo.h" |
16 |
#include "TargetInfo/ARMTargetInfo.h" |
| 17 |
#include "Utils/ARMBaseInfo.h" |
17 |
#include "Utils/ARMBaseInfo.h" |
| 18 |
#include "llvm/ADT/APFloat.h" |
18 |
#include "llvm/ADT/APFloat.h" |
| 19 |
#include "llvm/ADT/APInt.h" |
19 |
#include "llvm/ADT/APInt.h" |
| 20 |
#include "llvm/ADT/STLExtras.h" |
20 |
#include "llvm/ADT/STLExtras.h" |
| 21 |
#include "llvm/ADT/SmallSet.h" |
21 |
#include "llvm/ADT/SmallSet.h" |
| 22 |
#include "llvm/ADT/SmallVector.h" |
22 |
#include "llvm/ADT/SmallVector.h" |
| 23 |
#include "llvm/ADT/StringMap.h" |
23 |
#include "llvm/ADT/StringMap.h" |
| 24 |
#include "llvm/ADT/StringRef.h" |
24 |
#include "llvm/ADT/StringRef.h" |
| 25 |
#include "llvm/ADT/StringSet.h" |
25 |
#include "llvm/ADT/StringSet.h" |
| 26 |
#include "llvm/ADT/StringSwitch.h" |
26 |
#include "llvm/ADT/StringSwitch.h" |
| 27 |
#include "llvm/ADT/Twine.h" |
27 |
#include "llvm/ADT/Twine.h" |
| 28 |
#include "llvm/MC/MCContext.h" |
28 |
#include "llvm/MC/MCContext.h" |
| 29 |
#include "llvm/MC/MCExpr.h" |
29 |
#include "llvm/MC/MCExpr.h" |
| 30 |
#include "llvm/MC/MCInst.h" |
30 |
#include "llvm/MC/MCInst.h" |
| 31 |
#include "llvm/MC/MCInstrDesc.h" |
31 |
#include "llvm/MC/MCInstrDesc.h" |
| 32 |
#include "llvm/MC/MCInstrInfo.h" |
32 |
#include "llvm/MC/MCInstrInfo.h" |
| 33 |
#include "llvm/MC/MCParser/MCAsmLexer.h" |
33 |
#include "llvm/MC/MCParser/MCAsmLexer.h" |
| 34 |
#include "llvm/MC/MCParser/MCAsmParser.h" |
34 |
#include "llvm/MC/MCParser/MCAsmParser.h" |
| 35 |
#include "llvm/MC/MCParser/MCAsmParserExtension.h" |
35 |
#include "llvm/MC/MCParser/MCAsmParserExtension.h" |
| 36 |
#include "llvm/MC/MCParser/MCAsmParserUtils.h" |
36 |
#include "llvm/MC/MCParser/MCAsmParserUtils.h" |
| 37 |
#include "llvm/MC/MCParser/MCParsedAsmOperand.h" |
37 |
#include "llvm/MC/MCParser/MCParsedAsmOperand.h" |
| 38 |
#include "llvm/MC/MCParser/MCTargetAsmParser.h" |
38 |
#include "llvm/MC/MCParser/MCTargetAsmParser.h" |
| 39 |
#include "llvm/MC/MCRegisterInfo.h" |
39 |
#include "llvm/MC/MCRegisterInfo.h" |
| 40 |
#include "llvm/MC/MCSection.h" |
40 |
#include "llvm/MC/MCSection.h" |
| 41 |
#include "llvm/MC/MCStreamer.h" |
41 |
#include "llvm/MC/MCStreamer.h" |
| 42 |
#include "llvm/MC/MCSubtargetInfo.h" |
42 |
#include "llvm/MC/MCSubtargetInfo.h" |
| 43 |
#include "llvm/MC/MCSymbol.h" |
43 |
#include "llvm/MC/MCSymbol.h" |
| 44 |
#include "llvm/MC/TargetRegistry.h" |
44 |
#include "llvm/MC/TargetRegistry.h" |
| 45 |
#include "llvm/Support/ARMBuildAttributes.h" |
45 |
#include "llvm/Support/ARMBuildAttributes.h" |
| 46 |
#include "llvm/Support/ARMEHABI.h" |
46 |
#include "llvm/Support/ARMEHABI.h" |
| 47 |
#include "llvm/Support/Casting.h" |
47 |
#include "llvm/Support/Casting.h" |
| 48 |
#include "llvm/Support/CommandLine.h" |
48 |
#include "llvm/Support/CommandLine.h" |
| 49 |
#include "llvm/Support/Compiler.h" |
49 |
#include "llvm/Support/Compiler.h" |
| 50 |
#include "llvm/Support/ErrorHandling.h" |
50 |
#include "llvm/Support/ErrorHandling.h" |
| 51 |
#include "llvm/Support/MathExtras.h" |
51 |
#include "llvm/Support/MathExtras.h" |
| 52 |
#include "llvm/Support/SMLoc.h" |
52 |
#include "llvm/Support/SMLoc.h" |
| 53 |
#include "llvm/Support/raw_ostream.h" |
53 |
#include "llvm/Support/raw_ostream.h" |
| 54 |
#include "llvm/TargetParser/SubtargetFeature.h" |
54 |
#include "llvm/TargetParser/SubtargetFeature.h" |
| 55 |
#include "llvm/TargetParser/TargetParser.h" |
55 |
#include "llvm/TargetParser/TargetParser.h" |
| 56 |
#include "llvm/TargetParser/Triple.h" |
56 |
#include "llvm/TargetParser/Triple.h" |
| 57 |
#include |
57 |
#include |
| 58 |
#include |
58 |
#include |
| 59 |
#include |
59 |
#include |
| 60 |
#include |
60 |
#include |
| 61 |
#include |
61 |
#include |
| 62 |
#include |
62 |
#include |
| 63 |
#include |
63 |
#include |
| 64 |
#include |
64 |
#include |
| 65 |
#include |
65 |
#include |
| 66 |
#include |
66 |
#include |
| 67 |
|
67 |
|
| 68 |
#define DEBUG_TYPE "asm-parser" |
68 |
#define DEBUG_TYPE "asm-parser" |
| 69 |
|
69 |
|
| 70 |
using namespace llvm; |
70 |
using namespace llvm; |
| 71 |
|
71 |
|
| 72 |
namespace llvm { |
72 |
namespace llvm { |
| 73 |
struct ARMInstrTable { |
73 |
struct ARMInstrTable { |
| 74 |
MCInstrDesc Insts[4445]; |
74 |
MCInstrDesc Insts[4445]; |
| 75 |
MCOperandInfo OperandInfo[3026]; |
75 |
MCOperandInfo OperandInfo[3026]; |
| 76 |
MCPhysReg ImplicitOps[130]; |
76 |
MCPhysReg ImplicitOps[130]; |
| 77 |
}; |
77 |
}; |
| 78 |
extern const ARMInstrTable ARMDescs; |
78 |
extern const ARMInstrTable ARMDescs; |
| 79 |
} // end namespace llvm |
79 |
} // end namespace llvm |
| 80 |
|
80 |
|
| 81 |
namespace { |
81 |
namespace { |
| 82 |
|
82 |
|
| 83 |
enum class ImplicitItModeTy { Always, Never, ARMOnly, ThumbOnly }; |
83 |
enum class ImplicitItModeTy { Always, Never, ARMOnly, ThumbOnly }; |
| 84 |
|
84 |
|
| 85 |
static cl::opt ImplicitItMode( |
85 |
static cl::opt ImplicitItMode( |
| 86 |
"arm-implicit-it", cl::init(ImplicitItModeTy::ARMOnly), |
86 |
"arm-implicit-it", cl::init(ImplicitItModeTy::ARMOnly), |
| 87 |
cl::desc("Allow conditional instructions outdside of an IT block"), |
87 |
cl::desc("Allow conditional instructions outdside of an IT block"), |
| 88 |
cl::values(clEnumValN(ImplicitItModeTy::Always, "always", |
88 |
cl::values(clEnumValN(ImplicitItModeTy::Always, "always", |
| 89 |
"Accept in both ISAs, emit implicit ITs in Thumb"), |
89 |
"Accept in both ISAs, emit implicit ITs in Thumb"), |
| 90 |
clEnumValN(ImplicitItModeTy::Never, "never", |
90 |
clEnumValN(ImplicitItModeTy::Never, "never", |
| 91 |
"Warn in ARM, reject in Thumb"), |
91 |
"Warn in ARM, reject in Thumb"), |
| 92 |
clEnumValN(ImplicitItModeTy::ARMOnly, "arm", |
92 |
clEnumValN(ImplicitItModeTy::ARMOnly, "arm", |
| 93 |
"Accept in ARM, reject in Thumb"), |
93 |
"Accept in ARM, reject in Thumb"), |
| 94 |
clEnumValN(ImplicitItModeTy::ThumbOnly, "thumb", |
94 |
clEnumValN(ImplicitItModeTy::ThumbOnly, "thumb", |
| 95 |
"Warn in ARM, emit implicit ITs in Thumb"))); |
95 |
"Warn in ARM, emit implicit ITs in Thumb"))); |
| 96 |
|
96 |
|
| 97 |
static cl::opt AddBuildAttributes("arm-add-build-attributes", |
97 |
static cl::opt AddBuildAttributes("arm-add-build-attributes", |
| 98 |
cl::init(false)); |
98 |
cl::init(false)); |
| 99 |
|
99 |
|
| 100 |
enum VectorLaneTy { NoLanes, AllLanes, IndexedLane }; |
100 |
enum VectorLaneTy { NoLanes, AllLanes, IndexedLane }; |
| 101 |
|
101 |
|
| 102 |
static inline unsigned extractITMaskBit(unsigned Mask, unsigned Position) { |
102 |
static inline unsigned extractITMaskBit(unsigned Mask, unsigned Position) { |
| 103 |
// Position==0 means we're not in an IT block at all. Position==1 |
103 |
// Position==0 means we're not in an IT block at all. Position==1 |
| 104 |
// means we want the first state bit, which is always 0 (Then). |
104 |
// means we want the first state bit, which is always 0 (Then). |
| 105 |
// Position==2 means we want the second state bit, stored at bit 3 |
105 |
// Position==2 means we want the second state bit, stored at bit 3 |
| 106 |
// of Mask, and so on downwards. So (5 - Position) will shift the |
106 |
// of Mask, and so on downwards. So (5 - Position) will shift the |
| 107 |
// right bit down to bit 0, including the always-0 bit at bit 4 for |
107 |
// right bit down to bit 0, including the always-0 bit at bit 4 for |
| 108 |
// the mandatory initial Then. |
108 |
// the mandatory initial Then. |
| 109 |
return (Mask >> (5 - Position) & 1); |
109 |
return (Mask >> (5 - Position) & 1); |
| 110 |
} |
110 |
} |
| 111 |
|
111 |
|
| 112 |
class UnwindContext { |
112 |
class UnwindContext { |
| 113 |
using Locs = SmallVector; |
113 |
using Locs = SmallVector; |
| 114 |
|
114 |
|
| 115 |
MCAsmParser &Parser; |
115 |
MCAsmParser &Parser; |
| 116 |
Locs FnStartLocs; |
116 |
Locs FnStartLocs; |
| 117 |
Locs CantUnwindLocs; |
117 |
Locs CantUnwindLocs; |
| 118 |
Locs PersonalityLocs; |
118 |
Locs PersonalityLocs; |
| 119 |
Locs PersonalityIndexLocs; |
119 |
Locs PersonalityIndexLocs; |
| 120 |
Locs HandlerDataLocs; |
120 |
Locs HandlerDataLocs; |
| 121 |
int FPReg; |
121 |
int FPReg; |
| 122 |
|
122 |
|
| 123 |
public: |
123 |
public: |
| 124 |
UnwindContext(MCAsmParser &P) : Parser(P), FPReg(ARM::SP) {} |
124 |
UnwindContext(MCAsmParser &P) : Parser(P), FPReg(ARM::SP) {} |
| 125 |
|
125 |
|
| 126 |
bool hasFnStart() const { return !FnStartLocs.empty(); } |
126 |
bool hasFnStart() const { return !FnStartLocs.empty(); } |
| 127 |
bool cantUnwind() const { return !CantUnwindLocs.empty(); } |
127 |
bool cantUnwind() const { return !CantUnwindLocs.empty(); } |
| 128 |
bool hasHandlerData() const { return !HandlerDataLocs.empty(); } |
128 |
bool hasHandlerData() const { return !HandlerDataLocs.empty(); } |
| 129 |
|
129 |
|
| 130 |
bool hasPersonality() const { |
130 |
bool hasPersonality() const { |
| 131 |
return !(PersonalityLocs.empty() && PersonalityIndexLocs.empty()); |
131 |
return !(PersonalityLocs.empty() && PersonalityIndexLocs.empty()); |
| 132 |
} |
132 |
} |
| 133 |
|
133 |
|
| 134 |
void recordFnStart(SMLoc L) { FnStartLocs.push_back(L); } |
134 |
void recordFnStart(SMLoc L) { FnStartLocs.push_back(L); } |
| 135 |
void recordCantUnwind(SMLoc L) { CantUnwindLocs.push_back(L); } |
135 |
void recordCantUnwind(SMLoc L) { CantUnwindLocs.push_back(L); } |
| 136 |
void recordPersonality(SMLoc L) { PersonalityLocs.push_back(L); } |
136 |
void recordPersonality(SMLoc L) { PersonalityLocs.push_back(L); } |
| 137 |
void recordHandlerData(SMLoc L) { HandlerDataLocs.push_back(L); } |
137 |
void recordHandlerData(SMLoc L) { HandlerDataLocs.push_back(L); } |
| 138 |
void recordPersonalityIndex(SMLoc L) { PersonalityIndexLocs.push_back(L); } |
138 |
void recordPersonalityIndex(SMLoc L) { PersonalityIndexLocs.push_back(L); } |
| 139 |
|
139 |
|
| 140 |
void saveFPReg(int Reg) { FPReg = Reg; } |
140 |
void saveFPReg(int Reg) { FPReg = Reg; } |
| 141 |
int getFPReg() const { return FPReg; } |
141 |
int getFPReg() const { return FPReg; } |
| 142 |
|
142 |
|
| 143 |
void emitFnStartLocNotes() const { |
143 |
void emitFnStartLocNotes() const { |
| 144 |
for (const SMLoc &Loc : FnStartLocs) |
144 |
for (const SMLoc &Loc : FnStartLocs) |
| 145 |
Parser.Note(Loc, ".fnstart was specified here"); |
145 |
Parser.Note(Loc, ".fnstart was specified here"); |
| 146 |
} |
146 |
} |
| 147 |
|
147 |
|
| 148 |
void emitCantUnwindLocNotes() const { |
148 |
void emitCantUnwindLocNotes() const { |
| 149 |
for (const SMLoc &Loc : CantUnwindLocs) |
149 |
for (const SMLoc &Loc : CantUnwindLocs) |
| 150 |
Parser.Note(Loc, ".cantunwind was specified here"); |
150 |
Parser.Note(Loc, ".cantunwind was specified here"); |
| 151 |
} |
151 |
} |
| 152 |
|
152 |
|
| 153 |
void emitHandlerDataLocNotes() const { |
153 |
void emitHandlerDataLocNotes() const { |
| 154 |
for (const SMLoc &Loc : HandlerDataLocs) |
154 |
for (const SMLoc &Loc : HandlerDataLocs) |
| 155 |
Parser.Note(Loc, ".handlerdata was specified here"); |
155 |
Parser.Note(Loc, ".handlerdata was specified here"); |
| 156 |
} |
156 |
} |
| 157 |
|
157 |
|
| 158 |
void emitPersonalityLocNotes() const { |
158 |
void emitPersonalityLocNotes() const { |
| 159 |
for (Locs::const_iterator PI = PersonalityLocs.begin(), |
159 |
for (Locs::const_iterator PI = PersonalityLocs.begin(), |
| 160 |
PE = PersonalityLocs.end(), |
160 |
PE = PersonalityLocs.end(), |
| 161 |
PII = PersonalityIndexLocs.begin(), |
161 |
PII = PersonalityIndexLocs.begin(), |
| 162 |
PIE = PersonalityIndexLocs.end(); |
162 |
PIE = PersonalityIndexLocs.end(); |
| 163 |
PI != PE || PII != PIE;) { |
163 |
PI != PE || PII != PIE;) { |
| 164 |
if (PI != PE && (PII == PIE || PI->getPointer() < PII->getPointer())) |
164 |
if (PI != PE && (PII == PIE || PI->getPointer() < PII->getPointer())) |
| 165 |
Parser.Note(*PI++, ".personality was specified here"); |
165 |
Parser.Note(*PI++, ".personality was specified here"); |
| 166 |
else if (PII != PIE && (PI == PE || PII->getPointer() < PI->getPointer())) |
166 |
else if (PII != PIE && (PI == PE || PII->getPointer() < PI->getPointer())) |
| 167 |
Parser.Note(*PII++, ".personalityindex was specified here"); |
167 |
Parser.Note(*PII++, ".personalityindex was specified here"); |
| 168 |
else |
168 |
else |
| 169 |
llvm_unreachable(".personality and .personalityindex cannot be " |
169 |
llvm_unreachable(".personality and .personalityindex cannot be " |
| 170 |
"at the same location"); |
170 |
"at the same location"); |
| 171 |
} |
171 |
} |
| 172 |
} |
172 |
} |
| 173 |
|
173 |
|
| 174 |
void reset() { |
174 |
void reset() { |
| 175 |
FnStartLocs = Locs(); |
175 |
FnStartLocs = Locs(); |
| 176 |
CantUnwindLocs = Locs(); |
176 |
CantUnwindLocs = Locs(); |
| 177 |
PersonalityLocs = Locs(); |
177 |
PersonalityLocs = Locs(); |
| 178 |
HandlerDataLocs = Locs(); |
178 |
HandlerDataLocs = Locs(); |
| 179 |
PersonalityIndexLocs = Locs(); |
179 |
PersonalityIndexLocs = Locs(); |
| 180 |
FPReg = ARM::SP; |
180 |
FPReg = ARM::SP; |
| 181 |
} |
181 |
} |
| 182 |
}; |
182 |
}; |
| 183 |
|
183 |
|
| 184 |
// Various sets of ARM instruction mnemonics which are used by the asm parser |
184 |
// Various sets of ARM instruction mnemonics which are used by the asm parser |
| 185 |
class ARMMnemonicSets { |
185 |
class ARMMnemonicSets { |
| 186 |
StringSet<> CDE; |
186 |
StringSet<> CDE; |
| 187 |
StringSet<> CDEWithVPTSuffix; |
187 |
StringSet<> CDEWithVPTSuffix; |
| 188 |
public: |
188 |
public: |
| 189 |
ARMMnemonicSets(const MCSubtargetInfo &STI); |
189 |
ARMMnemonicSets(const MCSubtargetInfo &STI); |
| 190 |
|
190 |
|
| 191 |
/// Returns true iff a given mnemonic is a CDE instruction |
191 |
/// Returns true iff a given mnemonic is a CDE instruction |
| 192 |
bool isCDEInstr(StringRef Mnemonic) { |
192 |
bool isCDEInstr(StringRef Mnemonic) { |
| 193 |
// Quick check before searching the set |
193 |
// Quick check before searching the set |
| 194 |
if (!Mnemonic.startswith("cx") && !Mnemonic.startswith("vcx")) |
194 |
if (!Mnemonic.startswith("cx") && !Mnemonic.startswith("vcx")) |
| 195 |
return false; |
195 |
return false; |
| 196 |
return CDE.count(Mnemonic); |
196 |
return CDE.count(Mnemonic); |
| 197 |
} |
197 |
} |
| 198 |
|
198 |
|
| 199 |
/// Returns true iff a given mnemonic is a VPT-predicable CDE instruction |
199 |
/// Returns true iff a given mnemonic is a VPT-predicable CDE instruction |
| 200 |
/// (possibly with a predication suffix "e" or "t") |
200 |
/// (possibly with a predication suffix "e" or "t") |
| 201 |
bool isVPTPredicableCDEInstr(StringRef Mnemonic) { |
201 |
bool isVPTPredicableCDEInstr(StringRef Mnemonic) { |
| 202 |
if (!Mnemonic.startswith("vcx")) |
202 |
if (!Mnemonic.startswith("vcx")) |
| 203 |
return false; |
203 |
return false; |
| 204 |
return CDEWithVPTSuffix.count(Mnemonic); |
204 |
return CDEWithVPTSuffix.count(Mnemonic); |
| 205 |
} |
205 |
} |
| 206 |
|
206 |
|
| 207 |
/// Returns true iff a given mnemonic is an IT-predicable CDE instruction |
207 |
/// Returns true iff a given mnemonic is an IT-predicable CDE instruction |
| 208 |
/// (possibly with a condition suffix) |
208 |
/// (possibly with a condition suffix) |
| 209 |
bool isITPredicableCDEInstr(StringRef Mnemonic) { |
209 |
bool isITPredicableCDEInstr(StringRef Mnemonic) { |
| 210 |
if (!Mnemonic.startswith("cx")) |
210 |
if (!Mnemonic.startswith("cx")) |
| 211 |
return false; |
211 |
return false; |
| 212 |
return Mnemonic.startswith("cx1a") || Mnemonic.startswith("cx1da") || |
212 |
return Mnemonic.startswith("cx1a") || Mnemonic.startswith("cx1da") || |
| 213 |
Mnemonic.startswith("cx2a") || Mnemonic.startswith("cx2da") || |
213 |
Mnemonic.startswith("cx2a") || Mnemonic.startswith("cx2da") || |
| 214 |
Mnemonic.startswith("cx3a") || Mnemonic.startswith("cx3da"); |
214 |
Mnemonic.startswith("cx3a") || Mnemonic.startswith("cx3da"); |
| 215 |
} |
215 |
} |
| 216 |
|
216 |
|
| 217 |
/// Return true iff a given mnemonic is an integer CDE instruction with |
217 |
/// Return true iff a given mnemonic is an integer CDE instruction with |
| 218 |
/// dual-register destination |
218 |
/// dual-register destination |
| 219 |
bool isCDEDualRegInstr(StringRef Mnemonic) { |
219 |
bool isCDEDualRegInstr(StringRef Mnemonic) { |
| 220 |
if (!Mnemonic.startswith("cx")) |
220 |
if (!Mnemonic.startswith("cx")) |
| 221 |
return false; |
221 |
return false; |
| 222 |
return Mnemonic == "cx1d" || Mnemonic == "cx1da" || |
222 |
return Mnemonic == "cx1d" || Mnemonic == "cx1da" || |
| 223 |
Mnemonic == "cx2d" || Mnemonic == "cx2da" || |
223 |
Mnemonic == "cx2d" || Mnemonic == "cx2da" || |
| 224 |
Mnemonic == "cx3d" || Mnemonic == "cx3da"; |
224 |
Mnemonic == "cx3d" || Mnemonic == "cx3da"; |
| 225 |
} |
225 |
} |
| 226 |
}; |
226 |
}; |
| 227 |
|
227 |
|
| 228 |
ARMMnemonicSets::ARMMnemonicSets(const MCSubtargetInfo &STI) { |
228 |
ARMMnemonicSets::ARMMnemonicSets(const MCSubtargetInfo &STI) { |
| 229 |
for (StringRef Mnemonic: { "cx1", "cx1a", "cx1d", "cx1da", |
229 |
for (StringRef Mnemonic: { "cx1", "cx1a", "cx1d", "cx1da", |
| 230 |
"cx2", "cx2a", "cx2d", "cx2da", |
230 |
"cx2", "cx2a", "cx2d", "cx2da", |
| 231 |
"cx3", "cx3a", "cx3d", "cx3da", }) |
231 |
"cx3", "cx3a", "cx3d", "cx3da", }) |
| 232 |
CDE.insert(Mnemonic); |
232 |
CDE.insert(Mnemonic); |
| 233 |
for (StringRef Mnemonic : |
233 |
for (StringRef Mnemonic : |
| 234 |
{"vcx1", "vcx1a", "vcx2", "vcx2a", "vcx3", "vcx3a"}) { |
234 |
{"vcx1", "vcx1a", "vcx2", "vcx2a", "vcx3", "vcx3a"}) { |
| 235 |
CDE.insert(Mnemonic); |
235 |
CDE.insert(Mnemonic); |
| 236 |
CDEWithVPTSuffix.insert(Mnemonic); |
236 |
CDEWithVPTSuffix.insert(Mnemonic); |
| 237 |
CDEWithVPTSuffix.insert(std::string(Mnemonic) + "t"); |
237 |
CDEWithVPTSuffix.insert(std::string(Mnemonic) + "t"); |
| 238 |
CDEWithVPTSuffix.insert(std::string(Mnemonic) + "e"); |
238 |
CDEWithVPTSuffix.insert(std::string(Mnemonic) + "e"); |
| 239 |
} |
239 |
} |
| 240 |
} |
240 |
} |
| 241 |
|
241 |
|
| 242 |
class ARMAsmParser : public MCTargetAsmParser { |
242 |
class ARMAsmParser : public MCTargetAsmParser { |
| 243 |
const MCRegisterInfo *MRI; |
243 |
const MCRegisterInfo *MRI; |
| 244 |
UnwindContext UC; |
244 |
UnwindContext UC; |
| 245 |
ARMMnemonicSets MS; |
245 |
ARMMnemonicSets MS; |
| 246 |
|
246 |
|
| 247 |
ARMTargetStreamer &getTargetStreamer() { |
247 |
ARMTargetStreamer &getTargetStreamer() { |
| 248 |
assert(getParser().getStreamer().getTargetStreamer() && |
248 |
assert(getParser().getStreamer().getTargetStreamer() && |
| 249 |
"do not have a target streamer"); |
249 |
"do not have a target streamer"); |
| 250 |
MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); |
250 |
MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); |
| 251 |
return static_cast(TS); |
251 |
return static_cast(TS); |
| 252 |
} |
252 |
} |
| 253 |
|
253 |
|
| 254 |
// Map of register aliases registers via the .req directive. |
254 |
// Map of register aliases registers via the .req directive. |
| 255 |
StringMap RegisterReqs; |
255 |
StringMap RegisterReqs; |
| 256 |
|
256 |
|
| 257 |
bool NextSymbolIsThumb; |
257 |
bool NextSymbolIsThumb; |
| 258 |
|
258 |
|
| 259 |
bool useImplicitITThumb() const { |
259 |
bool useImplicitITThumb() const { |
| 260 |
return ImplicitItMode == ImplicitItModeTy::Always || |
260 |
return ImplicitItMode == ImplicitItModeTy::Always || |
| 261 |
ImplicitItMode == ImplicitItModeTy::ThumbOnly; |
261 |
ImplicitItMode == ImplicitItModeTy::ThumbOnly; |
| 262 |
} |
262 |
} |
| 263 |
|
263 |
|
| 264 |
bool useImplicitITARM() const { |
264 |
bool useImplicitITARM() const { |
| 265 |
return ImplicitItMode == ImplicitItModeTy::Always || |
265 |
return ImplicitItMode == ImplicitItModeTy::Always || |
| 266 |
ImplicitItMode == ImplicitItModeTy::ARMOnly; |
266 |
ImplicitItMode == ImplicitItModeTy::ARMOnly; |
| 267 |
} |
267 |
} |
| 268 |
|
268 |
|
| 269 |
struct { |
269 |
struct { |
| 270 |
ARMCC::CondCodes Cond; // Condition for IT block. |
270 |
ARMCC::CondCodes Cond; // Condition for IT block. |
| 271 |
unsigned Mask:4; // Condition mask for instructions. |
271 |
unsigned Mask:4; // Condition mask for instructions. |
| 272 |
// Starting at first 1 (from lsb). |
272 |
// Starting at first 1 (from lsb). |
| 273 |
// '1' condition as indicated in IT. |
273 |
// '1' condition as indicated in IT. |
| 274 |
// '0' inverse of condition (else). |
274 |
// '0' inverse of condition (else). |
| 275 |
// Count of instructions in IT block is |
275 |
// Count of instructions in IT block is |
| 276 |
// 4 - trailingzeroes(mask) |
276 |
// 4 - trailingzeroes(mask) |
| 277 |
// Note that this does not have the same encoding |
277 |
// Note that this does not have the same encoding |
| 278 |
// as in the IT instruction, which also depends |
278 |
// as in the IT instruction, which also depends |
| 279 |
// on the low bit of the condition code. |
279 |
// on the low bit of the condition code. |
| 280 |
|
280 |
|
| 281 |
unsigned CurPosition; // Current position in parsing of IT |
281 |
unsigned CurPosition; // Current position in parsing of IT |
| 282 |
// block. In range [0,4], with 0 being the IT |
282 |
// block. In range [0,4], with 0 being the IT |
| 283 |
// instruction itself. Initialized according to |
283 |
// instruction itself. Initialized according to |
| 284 |
// count of instructions in block. ~0U if no |
284 |
// count of instructions in block. ~0U if no |
| 285 |
// active IT block. |
285 |
// active IT block. |
| 286 |
|
286 |
|
| 287 |
bool IsExplicit; // true - The IT instruction was present in the |
287 |
bool IsExplicit; // true - The IT instruction was present in the |
| 288 |
// input, we should not modify it. |
288 |
// input, we should not modify it. |
| 289 |
// false - The IT instruction was added |
289 |
// false - The IT instruction was added |
| 290 |
// implicitly, we can extend it if that |
290 |
// implicitly, we can extend it if that |
| 291 |
// would be legal. |
291 |
// would be legal. |
| 292 |
} ITState; |
292 |
} ITState; |
| 293 |
|
293 |
|
| 294 |
SmallVector PendingConditionalInsts; |
294 |
SmallVector PendingConditionalInsts; |
| 295 |
|
295 |
|
| 296 |
void flushPendingInstructions(MCStreamer &Out) override { |
296 |
void flushPendingInstructions(MCStreamer &Out) override { |
| 297 |
if (!inImplicitITBlock()) { |
297 |
if (!inImplicitITBlock()) { |
| 298 |
assert(PendingConditionalInsts.size() == 0); |
298 |
assert(PendingConditionalInsts.size() == 0); |
| 299 |
return; |
299 |
return; |
| 300 |
} |
300 |
} |
| 301 |
|
301 |
|
| 302 |
// Emit the IT instruction |
302 |
// Emit the IT instruction |
| 303 |
MCInst ITInst; |
303 |
MCInst ITInst; |
| 304 |
ITInst.setOpcode(ARM::t2IT); |
304 |
ITInst.setOpcode(ARM::t2IT); |
| 305 |
ITInst.addOperand(MCOperand::createImm(ITState.Cond)); |
305 |
ITInst.addOperand(MCOperand::createImm(ITState.Cond)); |
| 306 |
ITInst.addOperand(MCOperand::createImm(ITState.Mask)); |
306 |
ITInst.addOperand(MCOperand::createImm(ITState.Mask)); |
| 307 |
Out.emitInstruction(ITInst, getSTI()); |
307 |
Out.emitInstruction(ITInst, getSTI()); |
| 308 |
|
308 |
|
| 309 |
// Emit the conditional instructions |
309 |
// Emit the conditional instructions |
| 310 |
assert(PendingConditionalInsts.size() <= 4); |
310 |
assert(PendingConditionalInsts.size() <= 4); |
| 311 |
for (const MCInst &Inst : PendingConditionalInsts) { |
311 |
for (const MCInst &Inst : PendingConditionalInsts) { |
| 312 |
Out.emitInstruction(Inst, getSTI()); |
312 |
Out.emitInstruction(Inst, getSTI()); |
| 313 |
} |
313 |
} |
| 314 |
PendingConditionalInsts.clear(); |
314 |
PendingConditionalInsts.clear(); |
| 315 |
|
315 |
|
| 316 |
// Clear the IT state |
316 |
// Clear the IT state |
| 317 |
ITState.Mask = 0; |
317 |
ITState.Mask = 0; |
| 318 |
ITState.CurPosition = ~0U; |
318 |
ITState.CurPosition = ~0U; |
| 319 |
} |
319 |
} |
| 320 |
|
320 |
|
| 321 |
bool inITBlock() { return ITState.CurPosition != ~0U; } |
321 |
bool inITBlock() { return ITState.CurPosition != ~0U; } |
| 322 |
bool inExplicitITBlock() { return inITBlock() && ITState.IsExplicit; } |
322 |
bool inExplicitITBlock() { return inITBlock() && ITState.IsExplicit; } |
| 323 |
bool inImplicitITBlock() { return inITBlock() && !ITState.IsExplicit; } |
323 |
bool inImplicitITBlock() { return inITBlock() && !ITState.IsExplicit; } |
| 324 |
|
324 |
|
| 325 |
bool lastInITBlock() { |
325 |
bool lastInITBlock() { |
| 326 |
return ITState.CurPosition == 4 - (unsigned)llvm::countr_zero(ITState.Mask); |
326 |
return ITState.CurPosition == 4 - (unsigned)llvm::countr_zero(ITState.Mask); |
| 327 |
} |
327 |
} |
| 328 |
|
328 |
|
| 329 |
void forwardITPosition() { |
329 |
void forwardITPosition() { |
| 330 |
if (!inITBlock()) return; |
330 |
if (!inITBlock()) return; |
| 331 |
// Move to the next instruction in the IT block, if there is one. If not, |
331 |
// Move to the next instruction in the IT block, if there is one. If not, |
| 332 |
// mark the block as done, except for implicit IT blocks, which we leave |
332 |
// mark the block as done, except for implicit IT blocks, which we leave |
| 333 |
// open until we find an instruction that can't be added to it. |
333 |
// open until we find an instruction that can't be added to it. |
| 334 |
unsigned TZ = llvm::countr_zero(ITState.Mask); |
334 |
unsigned TZ = llvm::countr_zero(ITState.Mask); |
| 335 |
if (++ITState.CurPosition == 5 - TZ && ITState.IsExplicit) |
335 |
if (++ITState.CurPosition == 5 - TZ && ITState.IsExplicit) |
| 336 |
ITState.CurPosition = ~0U; // Done with the IT block after this. |
336 |
ITState.CurPosition = ~0U; // Done with the IT block after this. |
| 337 |
} |
337 |
} |
| 338 |
|
338 |
|
| 339 |
// Rewind the state of the current IT block, removing the last slot from it. |
339 |
// Rewind the state of the current IT block, removing the last slot from it. |
| 340 |
void rewindImplicitITPosition() { |
340 |
void rewindImplicitITPosition() { |
| 341 |
assert(inImplicitITBlock()); |
341 |
assert(inImplicitITBlock()); |
| 342 |
assert(ITState.CurPosition > 1); |
342 |
assert(ITState.CurPosition > 1); |
| 343 |
ITState.CurPosition--; |
343 |
ITState.CurPosition--; |
| 344 |
unsigned TZ = llvm::countr_zero(ITState.Mask); |
344 |
unsigned TZ = llvm::countr_zero(ITState.Mask); |
| 345 |
unsigned NewMask = 0; |
345 |
unsigned NewMask = 0; |
| 346 |
NewMask |= ITState.Mask & (0xC << TZ); |
346 |
NewMask |= ITState.Mask & (0xC << TZ); |
| 347 |
NewMask |= 0x2 << TZ; |
347 |
NewMask |= 0x2 << TZ; |
| 348 |
ITState.Mask = NewMask; |
348 |
ITState.Mask = NewMask; |
| 349 |
} |
349 |
} |
| 350 |
|
350 |
|
| 351 |
// Rewind the state of the current IT block, removing the last slot from it. |
351 |
// Rewind the state of the current IT block, removing the last slot from it. |
| 352 |
// If we were at the first slot, this closes the IT block. |
352 |
// If we were at the first slot, this closes the IT block. |
| 353 |
void discardImplicitITBlock() { |
353 |
void discardImplicitITBlock() { |
| 354 |
assert(inImplicitITBlock()); |
354 |
assert(inImplicitITBlock()); |
| 355 |
assert(ITState.CurPosition == 1); |
355 |
assert(ITState.CurPosition == 1); |
| 356 |
ITState.CurPosition = ~0U; |
356 |
ITState.CurPosition = ~0U; |
| 357 |
} |
357 |
} |
| 358 |
|
358 |
|
| 359 |
// Return the low-subreg of a given Q register. |
359 |
// Return the low-subreg of a given Q register. |
| 360 |
unsigned getDRegFromQReg(unsigned QReg) const { |
360 |
unsigned getDRegFromQReg(unsigned QReg) const { |
| 361 |
return MRI->getSubReg(QReg, ARM::dsub_0); |
361 |
return MRI->getSubReg(QReg, ARM::dsub_0); |
| 362 |
} |
362 |
} |
| 363 |
|
363 |
|
| 364 |
// Get the condition code corresponding to the current IT block slot. |
364 |
// Get the condition code corresponding to the current IT block slot. |
| 365 |
ARMCC::CondCodes currentITCond() { |
365 |
ARMCC::CondCodes currentITCond() { |
| 366 |
unsigned MaskBit = extractITMaskBit(ITState.Mask, ITState.CurPosition); |
366 |
unsigned MaskBit = extractITMaskBit(ITState.Mask, ITState.CurPosition); |
| 367 |
return MaskBit ? ARMCC::getOppositeCondition(ITState.Cond) : ITState.Cond; |
367 |
return MaskBit ? ARMCC::getOppositeCondition(ITState.Cond) : ITState.Cond; |
| 368 |
} |
368 |
} |
| 369 |
|
369 |
|
| 370 |
// Invert the condition of the current IT block slot without changing any |
370 |
// Invert the condition of the current IT block slot without changing any |
| 371 |
// other slots in the same block. |
371 |
// other slots in the same block. |
| 372 |
void invertCurrentITCondition() { |
372 |
void invertCurrentITCondition() { |
| 373 |
if (ITState.CurPosition == 1) { |
373 |
if (ITState.CurPosition == 1) { |
| 374 |
ITState.Cond = ARMCC::getOppositeCondition(ITState.Cond); |
374 |
ITState.Cond = ARMCC::getOppositeCondition(ITState.Cond); |
| 375 |
} else { |
375 |
} else { |
| 376 |
ITState.Mask ^= 1 << (5 - ITState.CurPosition); |
376 |
ITState.Mask ^= 1 << (5 - ITState.CurPosition); |
| 377 |
} |
377 |
} |
| 378 |
} |
378 |
} |
| 379 |
|
379 |
|
| 380 |
// Returns true if the current IT block is full (all 4 slots used). |
380 |
// Returns true if the current IT block is full (all 4 slots used). |
| 381 |
bool isITBlockFull() { |
381 |
bool isITBlockFull() { |
| 382 |
return inITBlock() && (ITState.Mask & 1); |
382 |
return inITBlock() && (ITState.Mask & 1); |
| 383 |
} |
383 |
} |
| 384 |
|
384 |
|
| 385 |
// Extend the current implicit IT block to have one more slot with the given |
385 |
// Extend the current implicit IT block to have one more slot with the given |
| 386 |
// condition code. |
386 |
// condition code. |
| 387 |
void extendImplicitITBlock(ARMCC::CondCodes Cond) { |
387 |
void extendImplicitITBlock(ARMCC::CondCodes Cond) { |
| 388 |
assert(inImplicitITBlock()); |
388 |
assert(inImplicitITBlock()); |
| 389 |
assert(!isITBlockFull()); |
389 |
assert(!isITBlockFull()); |
| 390 |
assert(Cond == ITState.Cond || |
390 |
assert(Cond == ITState.Cond || |
| 391 |
Cond == ARMCC::getOppositeCondition(ITState.Cond)); |
391 |
Cond == ARMCC::getOppositeCondition(ITState.Cond)); |
| 392 |
unsigned TZ = llvm::countr_zero(ITState.Mask); |
392 |
unsigned TZ = llvm::countr_zero(ITState.Mask); |
| 393 |
unsigned NewMask = 0; |
393 |
unsigned NewMask = 0; |
| 394 |
// Keep any existing condition bits. |
394 |
// Keep any existing condition bits. |
| 395 |
NewMask |= ITState.Mask & (0xE << TZ); |
395 |
NewMask |= ITState.Mask & (0xE << TZ); |
| 396 |
// Insert the new condition bit. |
396 |
// Insert the new condition bit. |
| 397 |
NewMask |= (Cond != ITState.Cond) << TZ; |
397 |
NewMask |= (Cond != ITState.Cond) << TZ; |
| 398 |
// Move the trailing 1 down one bit. |
398 |
// Move the trailing 1 down one bit. |
| 399 |
NewMask |= 1 << (TZ - 1); |
399 |
NewMask |= 1 << (TZ - 1); |
| 400 |
ITState.Mask = NewMask; |
400 |
ITState.Mask = NewMask; |
| 401 |
} |
401 |
} |
| 402 |
|
402 |
|
| 403 |
// Create a new implicit IT block with a dummy condition code. |
403 |
// Create a new implicit IT block with a dummy condition code. |
| 404 |
void startImplicitITBlock() { |
404 |
void startImplicitITBlock() { |
| 405 |
assert(!inITBlock()); |
405 |
assert(!inITBlock()); |
| 406 |
ITState.Cond = ARMCC::AL; |
406 |
ITState.Cond = ARMCC::AL; |
| 407 |
ITState.Mask = 8; |
407 |
ITState.Mask = 8; |
| 408 |
ITState.CurPosition = 1; |
408 |
ITState.CurPosition = 1; |
| 409 |
ITState.IsExplicit = false; |
409 |
ITState.IsExplicit = false; |
| 410 |
} |
410 |
} |
| 411 |
|
411 |
|
| 412 |
// Create a new explicit IT block with the given condition and mask. |
412 |
// Create a new explicit IT block with the given condition and mask. |
| 413 |
// The mask should be in the format used in ARMOperand and |
413 |
// The mask should be in the format used in ARMOperand and |
| 414 |
// MCOperand, with a 1 implying 'e', regardless of the low bit of |
414 |
// MCOperand, with a 1 implying 'e', regardless of the low bit of |
| 415 |
// the condition. |
415 |
// the condition. |
| 416 |
void startExplicitITBlock(ARMCC::CondCodes Cond, unsigned Mask) { |
416 |
void startExplicitITBlock(ARMCC::CondCodes Cond, unsigned Mask) { |
| 417 |
assert(!inITBlock()); |
417 |
assert(!inITBlock()); |
| 418 |
ITState.Cond = Cond; |
418 |
ITState.Cond = Cond; |
| 419 |
ITState.Mask = Mask; |
419 |
ITState.Mask = Mask; |
| 420 |
ITState.CurPosition = 0; |
420 |
ITState.CurPosition = 0; |
| 421 |
ITState.IsExplicit = true; |
421 |
ITState.IsExplicit = true; |
| 422 |
} |
422 |
} |
| 423 |
|
423 |
|
| 424 |
struct { |
424 |
struct { |
| 425 |
unsigned Mask : 4; |
425 |
unsigned Mask : 4; |
| 426 |
unsigned CurPosition; |
426 |
unsigned CurPosition; |
| 427 |
} VPTState; |
427 |
} VPTState; |
| 428 |
bool inVPTBlock() { return VPTState.CurPosition != ~0U; } |
428 |
bool inVPTBlock() { return VPTState.CurPosition != ~0U; } |
| 429 |
void forwardVPTPosition() { |
429 |
void forwardVPTPosition() { |
| 430 |
if (!inVPTBlock()) return; |
430 |
if (!inVPTBlock()) return; |
| 431 |
unsigned TZ = llvm::countr_zero(VPTState.Mask); |
431 |
unsigned TZ = llvm::countr_zero(VPTState.Mask); |
| 432 |
if (++VPTState.CurPosition == 5 - TZ) |
432 |
if (++VPTState.CurPosition == 5 - TZ) |
| 433 |
VPTState.CurPosition = ~0U; |
433 |
VPTState.CurPosition = ~0U; |
| 434 |
} |
434 |
} |
| 435 |
|
435 |
|
| 436 |
void Note(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) { |
436 |
void Note(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) { |
| 437 |
return getParser().Note(L, Msg, Range); |
437 |
return getParser().Note(L, Msg, Range); |
| 438 |
} |
438 |
} |
| 439 |
|
439 |
|
| 440 |
bool Warning(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) { |
440 |
bool Warning(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) { |
| 441 |
return getParser().Warning(L, Msg, Range); |
441 |
return getParser().Warning(L, Msg, Range); |
| 442 |
} |
442 |
} |
| 443 |
|
443 |
|
| 444 |
bool Error(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) { |
444 |
bool Error(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) { |
| 445 |
return getParser().Error(L, Msg, Range); |
445 |
return getParser().Error(L, Msg, Range); |
| 446 |
} |
446 |
} |
| 447 |
|
447 |
|
| 448 |
bool validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands, |
448 |
bool validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands, |
| 449 |
unsigned ListNo, bool IsARPop = false); |
449 |
unsigned ListNo, bool IsARPop = false); |
| 450 |
bool validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands, |
450 |
bool validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands, |
| 451 |
unsigned ListNo); |
451 |
unsigned ListNo); |
| 452 |
|
452 |
|
| 453 |
int tryParseRegister(); |
453 |
int tryParseRegister(); |
| 454 |
bool tryParseRegisterWithWriteBack(OperandVector &); |
454 |
bool tryParseRegisterWithWriteBack(OperandVector &); |
| 455 |
int tryParseShiftRegister(OperandVector &); |
455 |
int tryParseShiftRegister(OperandVector &); |
| 456 |
bool parseRegisterList(OperandVector &, bool EnforceOrder = true, |
456 |
bool parseRegisterList(OperandVector &, bool EnforceOrder = true, |
| 457 |
bool AllowRAAC = false); |
457 |
bool AllowRAAC = false); |
| 458 |
bool parseMemory(OperandVector &); |
458 |
bool parseMemory(OperandVector &); |
| 459 |
bool parseOperand(OperandVector &, StringRef Mnemonic); |
459 |
bool parseOperand(OperandVector &, StringRef Mnemonic); |
| 460 |
bool parseImmExpr(int64_t &Out); |
460 |
bool parseImmExpr(int64_t &Out); |
| 461 |
bool parsePrefix(ARMMCExpr::VariantKind &RefKind); |
461 |
bool parsePrefix(ARMMCExpr::VariantKind &RefKind); |
| 462 |
bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType, |
462 |
bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType, |
| 463 |
unsigned &ShiftAmount); |
463 |
unsigned &ShiftAmount); |
| 464 |
bool parseLiteralValues(unsigned Size, SMLoc L); |
464 |
bool parseLiteralValues(unsigned Size, SMLoc L); |
| 465 |
bool parseDirectiveThumb(SMLoc L); |
465 |
bool parseDirectiveThumb(SMLoc L); |
| 466 |
bool parseDirectiveARM(SMLoc L); |
466 |
bool parseDirectiveARM(SMLoc L); |
| 467 |
bool parseDirectiveThumbFunc(SMLoc L); |
467 |
bool parseDirectiveThumbFunc(SMLoc L); |
| 468 |
bool parseDirectiveCode(SMLoc L); |
468 |
bool parseDirectiveCode(SMLoc L); |
| 469 |
bool parseDirectiveSyntax(SMLoc L); |
469 |
bool parseDirectiveSyntax(SMLoc L); |
| 470 |
bool parseDirectiveReq(StringRef Name, SMLoc L); |
470 |
bool parseDirectiveReq(StringRef Name, SMLoc L); |
| 471 |
bool parseDirectiveUnreq(SMLoc L); |
471 |
bool parseDirectiveUnreq(SMLoc L); |
| 472 |
bool parseDirectiveArch(SMLoc L); |
472 |
bool parseDirectiveArch(SMLoc L); |
| 473 |
bool parseDirectiveEabiAttr(SMLoc L); |
473 |
bool parseDirectiveEabiAttr(SMLoc L); |
| 474 |
bool parseDirectiveCPU(SMLoc L); |
474 |
bool parseDirectiveCPU(SMLoc L); |
| 475 |
bool parseDirectiveFPU(SMLoc L); |
475 |
bool parseDirectiveFPU(SMLoc L); |
| 476 |
bool parseDirectiveFnStart(SMLoc L); |
476 |
bool parseDirectiveFnStart(SMLoc L); |
| 477 |
bool parseDirectiveFnEnd(SMLoc L); |
477 |
bool parseDirectiveFnEnd(SMLoc L); |
| 478 |
bool parseDirectiveCantUnwind(SMLoc L); |
478 |
bool parseDirectiveCantUnwind(SMLoc L); |
| 479 |
bool parseDirectivePersonality(SMLoc L); |
479 |
bool parseDirectivePersonality(SMLoc L); |
| 480 |
bool parseDirectiveHandlerData(SMLoc L); |
480 |
bool parseDirectiveHandlerData(SMLoc L); |
| 481 |
bool parseDirectiveSetFP(SMLoc L); |
481 |
bool parseDirectiveSetFP(SMLoc L); |
| 482 |
bool parseDirectivePad(SMLoc L); |
482 |
bool parseDirectivePad(SMLoc L); |
| 483 |
bool parseDirectiveRegSave(SMLoc L, bool IsVector); |
483 |
bool parseDirectiveRegSave(SMLoc L, bool IsVector); |
| 484 |
bool parseDirectiveInst(SMLoc L, char Suffix = '\0'); |
484 |
bool parseDirectiveInst(SMLoc L, char Suffix = '\0'); |
| 485 |
bool parseDirectiveLtorg(SMLoc L); |
485 |
bool parseDirectiveLtorg(SMLoc L); |
| 486 |
bool parseDirectiveEven(SMLoc L); |
486 |
bool parseDirectiveEven(SMLoc L); |
| 487 |
bool parseDirectivePersonalityIndex(SMLoc L); |
487 |
bool parseDirectivePersonalityIndex(SMLoc L); |
| 488 |
bool parseDirectiveUnwindRaw(SMLoc L); |
488 |
bool parseDirectiveUnwindRaw(SMLoc L); |
| 489 |
bool parseDirectiveTLSDescSeq(SMLoc L); |
489 |
bool parseDirectiveTLSDescSeq(SMLoc L); |
| 490 |
bool parseDirectiveMovSP(SMLoc L); |
490 |
bool parseDirectiveMovSP(SMLoc L); |
| 491 |
bool parseDirectiveObjectArch(SMLoc L); |
491 |
bool parseDirectiveObjectArch(SMLoc L); |
| 492 |
bool parseDirectiveArchExtension(SMLoc L); |
492 |
bool parseDirectiveArchExtension(SMLoc L); |
| 493 |
bool parseDirectiveAlign(SMLoc L); |
493 |
bool parseDirectiveAlign(SMLoc L); |
| 494 |
bool parseDirectiveThumbSet(SMLoc L); |
494 |
bool parseDirectiveThumbSet(SMLoc L); |
| 495 |
|
495 |
|
| 496 |
bool parseDirectiveSEHAllocStack(SMLoc L, bool Wide); |
496 |
bool parseDirectiveSEHAllocStack(SMLoc L, bool Wide); |
| 497 |
bool parseDirectiveSEHSaveRegs(SMLoc L, bool Wide); |
497 |
bool parseDirectiveSEHSaveRegs(SMLoc L, bool Wide); |
| 498 |
bool parseDirectiveSEHSaveSP(SMLoc L); |
498 |
bool parseDirectiveSEHSaveSP(SMLoc L); |
| 499 |
bool parseDirectiveSEHSaveFRegs(SMLoc L); |
499 |
bool parseDirectiveSEHSaveFRegs(SMLoc L); |
| 500 |
bool parseDirectiveSEHSaveLR(SMLoc L); |
500 |
bool parseDirectiveSEHSaveLR(SMLoc L); |
| 501 |
bool parseDirectiveSEHPrologEnd(SMLoc L, bool Fragment); |
501 |
bool parseDirectiveSEHPrologEnd(SMLoc L, bool Fragment); |
| 502 |
bool parseDirectiveSEHNop(SMLoc L, bool Wide); |
502 |
bool parseDirectiveSEHNop(SMLoc L, bool Wide); |
| 503 |
bool parseDirectiveSEHEpilogStart(SMLoc L, bool Condition); |
503 |
bool parseDirectiveSEHEpilogStart(SMLoc L, bool Condition); |
| 504 |
bool parseDirectiveSEHEpilogEnd(SMLoc L); |
504 |
bool parseDirectiveSEHEpilogEnd(SMLoc L); |
| 505 |
bool parseDirectiveSEHCustom(SMLoc L); |
505 |
bool parseDirectiveSEHCustom(SMLoc L); |
| 506 |
|
506 |
|
| 507 |
bool isMnemonicVPTPredicable(StringRef Mnemonic, StringRef ExtraToken); |
507 |
bool isMnemonicVPTPredicable(StringRef Mnemonic, StringRef ExtraToken); |
| 508 |
StringRef splitMnemonic(StringRef Mnemonic, StringRef ExtraToken, |
508 |
StringRef splitMnemonic(StringRef Mnemonic, StringRef ExtraToken, |
| 509 |
unsigned &PredicationCode, |
509 |
unsigned &PredicationCode, |
| 510 |
unsigned &VPTPredicationCode, bool &CarrySetting, |
510 |
unsigned &VPTPredicationCode, bool &CarrySetting, |
| 511 |
unsigned &ProcessorIMod, StringRef &ITMask); |
511 |
unsigned &ProcessorIMod, StringRef &ITMask); |
| 512 |
void getMnemonicAcceptInfo(StringRef Mnemonic, StringRef ExtraToken, |
512 |
void getMnemonicAcceptInfo(StringRef Mnemonic, StringRef ExtraToken, |
| 513 |
StringRef FullInst, bool &CanAcceptCarrySet, |
513 |
StringRef FullInst, bool &CanAcceptCarrySet, |
| 514 |
bool &CanAcceptPredicationCode, |
514 |
bool &CanAcceptPredicationCode, |
| 515 |
bool &CanAcceptVPTPredicationCode); |
515 |
bool &CanAcceptVPTPredicationCode); |
| 516 |
bool enableArchExtFeature(StringRef Name, SMLoc &ExtLoc); |
516 |
bool enableArchExtFeature(StringRef Name, SMLoc &ExtLoc); |
| 517 |
|
517 |
|
| 518 |
void tryConvertingToTwoOperandForm(StringRef Mnemonic, bool CarrySetting, |
518 |
void tryConvertingToTwoOperandForm(StringRef Mnemonic, bool CarrySetting, |
| 519 |
OperandVector &Operands); |
519 |
OperandVector &Operands); |
| 520 |
bool CDEConvertDualRegOperand(StringRef Mnemonic, OperandVector &Operands); |
520 |
bool CDEConvertDualRegOperand(StringRef Mnemonic, OperandVector &Operands); |
| 521 |
|
521 |
|
| 522 |
bool isThumb() const { |
522 |
bool isThumb() const { |
| 523 |
// FIXME: Can tablegen auto-generate this? |
523 |
// FIXME: Can tablegen auto-generate this? |
| 524 |
return getSTI().hasFeature(ARM::ModeThumb); |
524 |
return getSTI().hasFeature(ARM::ModeThumb); |
| 525 |
} |
525 |
} |
| 526 |
|
526 |
|
| 527 |
bool isThumbOne() const { |
527 |
bool isThumbOne() const { |
| 528 |
return isThumb() && !getSTI().hasFeature(ARM::FeatureThumb2); |
528 |
return isThumb() && !getSTI().hasFeature(ARM::FeatureThumb2); |
| 529 |
} |
529 |
} |
| 530 |
|
530 |
|
| 531 |
bool isThumbTwo() const { |
531 |
bool isThumbTwo() const { |
| 532 |
return isThumb() && getSTI().hasFeature(ARM::FeatureThumb2); |
532 |
return isThumb() && getSTI().hasFeature(ARM::FeatureThumb2); |
| 533 |
} |
533 |
} |
| 534 |
|
534 |
|
| 535 |
bool hasThumb() const { |
535 |
bool hasThumb() const { |
| 536 |
return getSTI().hasFeature(ARM::HasV4TOps); |
536 |
return getSTI().hasFeature(ARM::HasV4TOps); |
| 537 |
} |
537 |
} |
| 538 |
|
538 |
|
| 539 |
bool hasThumb2() const { |
539 |
bool hasThumb2() const { |
| 540 |
return getSTI().hasFeature(ARM::FeatureThumb2); |
540 |
return getSTI().hasFeature(ARM::FeatureThumb2); |
| 541 |
} |
541 |
} |
| 542 |
|
542 |
|
| 543 |
bool hasV6Ops() const { |
543 |
bool hasV6Ops() const { |
| 544 |
return getSTI().hasFeature(ARM::HasV6Ops); |
544 |
return getSTI().hasFeature(ARM::HasV6Ops); |
| 545 |
} |
545 |
} |
| 546 |
|
546 |
|
| 547 |
bool hasV6T2Ops() const { |
547 |
bool hasV6T2Ops() const { |
| 548 |
return getSTI().hasFeature(ARM::HasV6T2Ops); |
548 |
return getSTI().hasFeature(ARM::HasV6T2Ops); |
| 549 |
} |
549 |
} |
| 550 |
|
550 |
|
| 551 |
bool hasV6MOps() const { |
551 |
bool hasV6MOps() const { |
| 552 |
return getSTI().hasFeature(ARM::HasV6MOps); |
552 |
return getSTI().hasFeature(ARM::HasV6MOps); |
| 553 |
} |
553 |
} |
| 554 |
|
554 |
|
| 555 |
bool hasV7Ops() const { |
555 |
bool hasV7Ops() const { |
| 556 |
return getSTI().hasFeature(ARM::HasV7Ops); |
556 |
return getSTI().hasFeature(ARM::HasV7Ops); |
| 557 |
} |
557 |
} |
| 558 |
|
558 |
|
| 559 |
bool hasV8Ops() const { |
559 |
bool hasV8Ops() const { |
| 560 |
return getSTI().hasFeature(ARM::HasV8Ops); |
560 |
return getSTI().hasFeature(ARM::HasV8Ops); |
| 561 |
} |
561 |
} |
| 562 |
|
562 |
|
| 563 |
bool hasV8MBaseline() const { |
563 |
bool hasV8MBaseline() const { |
| 564 |
return getSTI().hasFeature(ARM::HasV8MBaselineOps); |
564 |
return getSTI().hasFeature(ARM::HasV8MBaselineOps); |
| 565 |
} |
565 |
} |
| 566 |
|
566 |
|
| 567 |
bool hasV8MMainline() const { |
567 |
bool hasV8MMainline() const { |
| 568 |
return getSTI().hasFeature(ARM::HasV8MMainlineOps); |
568 |
return getSTI().hasFeature(ARM::HasV8MMainlineOps); |
| 569 |
} |
569 |
} |
| 570 |
bool hasV8_1MMainline() const { |
570 |
bool hasV8_1MMainline() const { |
| 571 |
return getSTI().hasFeature(ARM::HasV8_1MMainlineOps); |
571 |
return getSTI().hasFeature(ARM::HasV8_1MMainlineOps); |
| 572 |
} |
572 |
} |
| 573 |
bool hasMVE() const { |
573 |
bool hasMVE() const { |
| 574 |
return getSTI().hasFeature(ARM::HasMVEIntegerOps); |
574 |
return getSTI().hasFeature(ARM::HasMVEIntegerOps); |
| 575 |
} |
575 |
} |
| 576 |
bool hasMVEFloat() const { |
576 |
bool hasMVEFloat() const { |
| 577 |
return getSTI().hasFeature(ARM::HasMVEFloatOps); |
577 |
return getSTI().hasFeature(ARM::HasMVEFloatOps); |
| 578 |
} |
578 |
} |
| 579 |
bool hasCDE() const { |
579 |
bool hasCDE() const { |
| 580 |
return getSTI().hasFeature(ARM::HasCDEOps); |
580 |
return getSTI().hasFeature(ARM::HasCDEOps); |
| 581 |
} |
581 |
} |
| 582 |
bool has8MSecExt() const { |
582 |
bool has8MSecExt() const { |
| 583 |
return getSTI().hasFeature(ARM::Feature8MSecExt); |
583 |
return getSTI().hasFeature(ARM::Feature8MSecExt); |
| 584 |
} |
584 |
} |
| 585 |
|
585 |
|
| 586 |
bool hasARM() const { |
586 |
bool hasARM() const { |
| 587 |
return !getSTI().hasFeature(ARM::FeatureNoARM); |
587 |
return !getSTI().hasFeature(ARM::FeatureNoARM); |
| 588 |
} |
588 |
} |
| 589 |
|
589 |
|
| 590 |
bool hasDSP() const { |
590 |
bool hasDSP() const { |
| 591 |
return getSTI().hasFeature(ARM::FeatureDSP); |
591 |
return getSTI().hasFeature(ARM::FeatureDSP); |
| 592 |
} |
592 |
} |
| 593 |
|
593 |
|
| 594 |
bool hasD32() const { |
594 |
bool hasD32() const { |
| 595 |
return getSTI().hasFeature(ARM::FeatureD32); |
595 |
return getSTI().hasFeature(ARM::FeatureD32); |
| 596 |
} |
596 |
} |
| 597 |
|
597 |
|
| 598 |
bool hasV8_1aOps() const { |
598 |
bool hasV8_1aOps() const { |
| 599 |
return getSTI().hasFeature(ARM::HasV8_1aOps); |
599 |
return getSTI().hasFeature(ARM::HasV8_1aOps); |
| 600 |
} |
600 |
} |
| 601 |
|
601 |
|
| 602 |
bool hasRAS() const { |
602 |
bool hasRAS() const { |
| 603 |
return getSTI().hasFeature(ARM::FeatureRAS); |
603 |
return getSTI().hasFeature(ARM::FeatureRAS); |
| 604 |
} |
604 |
} |
| 605 |
|
605 |
|
| 606 |
void SwitchMode() { |
606 |
void SwitchMode() { |
| 607 |
MCSubtargetInfo &STI = copySTI(); |
607 |
MCSubtargetInfo &STI = copySTI(); |
| 608 |
auto FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); |
608 |
auto FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); |
| 609 |
setAvailableFeatures(FB); |
609 |
setAvailableFeatures(FB); |
| 610 |
} |
610 |
} |
| 611 |
|
611 |
|
| 612 |
void FixModeAfterArchChange(bool WasThumb, SMLoc Loc); |
612 |
void FixModeAfterArchChange(bool WasThumb, SMLoc Loc); |
| 613 |
|
613 |
|
| 614 |
bool isMClass() const { |
614 |
bool isMClass() const { |
| 615 |
return getSTI().hasFeature(ARM::FeatureMClass); |
615 |
return getSTI().hasFeature(ARM::FeatureMClass); |
| 616 |
} |
616 |
} |
| 617 |
|
617 |
|
| 618 |
/// @name Auto-generated Match Functions |
618 |
/// @name Auto-generated Match Functions |
| 619 |
/// { |
619 |
/// { |
| 620 |
|
620 |
|
| 621 |
#define GET_ASSEMBLER_HEADER |
621 |
#define GET_ASSEMBLER_HEADER |
| 622 |
#include "ARMGenAsmMatcher.inc" |
622 |
#include "ARMGenAsmMatcher.inc" |
| 623 |
|
623 |
|
| 624 |
/// } |
624 |
/// } |
| 625 |
|
625 |
|
| 626 |
ParseStatus parseITCondCode(OperandVector &); |
626 |
ParseStatus parseITCondCode(OperandVector &); |
| 627 |
ParseStatus parseCoprocNumOperand(OperandVector &); |
627 |
ParseStatus parseCoprocNumOperand(OperandVector &); |
| 628 |
ParseStatus parseCoprocRegOperand(OperandVector &); |
628 |
ParseStatus parseCoprocRegOperand(OperandVector &); |
| 629 |
ParseStatus parseCoprocOptionOperand(OperandVector &); |
629 |
ParseStatus parseCoprocOptionOperand(OperandVector &); |
| 630 |
ParseStatus parseMemBarrierOptOperand(OperandVector &); |
630 |
ParseStatus parseMemBarrierOptOperand(OperandVector &); |
| 631 |
ParseStatus parseTraceSyncBarrierOptOperand(OperandVector &); |
631 |
ParseStatus parseTraceSyncBarrierOptOperand(OperandVector &); |
| 632 |
ParseStatus parseInstSyncBarrierOptOperand(OperandVector &); |
632 |
ParseStatus parseInstSyncBarrierOptOperand(OperandVector &); |
| 633 |
ParseStatus parseProcIFlagsOperand(OperandVector &); |
633 |
ParseStatus parseProcIFlagsOperand(OperandVector &); |
| 634 |
ParseStatus parseMSRMaskOperand(OperandVector &); |
634 |
ParseStatus parseMSRMaskOperand(OperandVector &); |
| 635 |
ParseStatus parseBankedRegOperand(OperandVector &); |
635 |
ParseStatus parseBankedRegOperand(OperandVector &); |
| 636 |
ParseStatus parsePKHImm(OperandVector &O, StringRef Op, int Low, int High); |
636 |
ParseStatus parsePKHImm(OperandVector &O, StringRef Op, int Low, int High); |
| 637 |
ParseStatus parsePKHLSLImm(OperandVector &O) { |
637 |
ParseStatus parsePKHLSLImm(OperandVector &O) { |
| 638 |
return parsePKHImm(O, "lsl", 0, 31); |
638 |
return parsePKHImm(O, "lsl", 0, 31); |
| 639 |
} |
639 |
} |
| 640 |
ParseStatus parsePKHASRImm(OperandVector &O) { |
640 |
ParseStatus parsePKHASRImm(OperandVector &O) { |
| 641 |
return parsePKHImm(O, "asr", 1, 32); |
641 |
return parsePKHImm(O, "asr", 1, 32); |
| 642 |
} |
642 |
} |
| 643 |
ParseStatus parseSetEndImm(OperandVector &); |
643 |
ParseStatus parseSetEndImm(OperandVector &); |
| 644 |
ParseStatus parseShifterImm(OperandVector &); |
644 |
ParseStatus parseShifterImm(OperandVector &); |
| 645 |
ParseStatus parseRotImm(OperandVector &); |
645 |
ParseStatus parseRotImm(OperandVector &); |
| 646 |
ParseStatus parseModImm(OperandVector &); |
646 |
ParseStatus parseModImm(OperandVector &); |
| 647 |
ParseStatus parseBitfield(OperandVector &); |
647 |
ParseStatus parseBitfield(OperandVector &); |
| 648 |
ParseStatus parsePostIdxReg(OperandVector &); |
648 |
ParseStatus parsePostIdxReg(OperandVector &); |
| 649 |
ParseStatus parseAM3Offset(OperandVector &); |
649 |
ParseStatus parseAM3Offset(OperandVector &); |
| 650 |
ParseStatus parseFPImm(OperandVector &); |
650 |
ParseStatus parseFPImm(OperandVector &); |
| 651 |
ParseStatus parseVectorList(OperandVector &); |
651 |
ParseStatus parseVectorList(OperandVector &); |
| 652 |
ParseStatus parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, |
652 |
ParseStatus parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, |
| 653 |
SMLoc &EndLoc); |
653 |
SMLoc &EndLoc); |
| 654 |
|
654 |
|
| 655 |
// Asm Match Converter Methods |
655 |
// Asm Match Converter Methods |
| 656 |
void cvtThumbMultiply(MCInst &Inst, const OperandVector &); |
656 |
void cvtThumbMultiply(MCInst &Inst, const OperandVector &); |
| 657 |
void cvtThumbBranches(MCInst &Inst, const OperandVector &); |
657 |
void cvtThumbBranches(MCInst &Inst, const OperandVector &); |
| 658 |
void cvtMVEVMOVQtoDReg(MCInst &Inst, const OperandVector &); |
658 |
void cvtMVEVMOVQtoDReg(MCInst &Inst, const OperandVector &); |
| 659 |
|
659 |
|
| 660 |
bool validateInstruction(MCInst &Inst, const OperandVector &Ops); |
660 |
bool validateInstruction(MCInst &Inst, const OperandVector &Ops); |
| 661 |
bool processInstruction(MCInst &Inst, const OperandVector &Ops, MCStreamer &Out); |
661 |
bool processInstruction(MCInst &Inst, const OperandVector &Ops, MCStreamer &Out); |
| 662 |
bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands); |
662 |
bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands); |
| 663 |
bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands); |
663 |
bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands); |
| 664 |
bool shouldOmitVectorPredicateOperand(StringRef Mnemonic, OperandVector &Operands); |
664 |
bool shouldOmitVectorPredicateOperand(StringRef Mnemonic, OperandVector &Operands); |
| 665 |
bool isITBlockTerminator(MCInst &Inst) const; |
665 |
bool isITBlockTerminator(MCInst &Inst) const; |
| 666 |
void fixupGNULDRDAlias(StringRef Mnemonic, OperandVector &Operands); |
666 |
void fixupGNULDRDAlias(StringRef Mnemonic, OperandVector &Operands); |
| 667 |
bool validateLDRDSTRD(MCInst &Inst, const OperandVector &Operands, |
667 |
bool validateLDRDSTRD(MCInst &Inst, const OperandVector &Operands, |
| 668 |
bool Load, bool ARMMode, bool Writeback); |
668 |
bool Load, bool ARMMode, bool Writeback); |
| 669 |
|
669 |
|
| 670 |
public: |
670 |
public: |
| 671 |
enum ARMMatchResultTy { |
671 |
enum ARMMatchResultTy { |
| 672 |
Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY, |
672 |
Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY, |
| 673 |
Match_RequiresNotITBlock, |
673 |
Match_RequiresNotITBlock, |
| 674 |
Match_RequiresV6, |
674 |
Match_RequiresV6, |
| 675 |
Match_RequiresThumb2, |
675 |
Match_RequiresThumb2, |
| 676 |
Match_RequiresV8, |
676 |
Match_RequiresV8, |
| 677 |
Match_RequiresFlagSetting, |
677 |
Match_RequiresFlagSetting, |
| 678 |
#define GET_OPERAND_DIAGNOSTIC_TYPES |
678 |
#define GET_OPERAND_DIAGNOSTIC_TYPES |
| 679 |
#include "ARMGenAsmMatcher.inc" |
679 |
#include "ARMGenAsmMatcher.inc" |
| 680 |
|
680 |
|
| 681 |
}; |
681 |
}; |
| 682 |
|
682 |
|
| 683 |
ARMAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, |
683 |
ARMAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, |
| 684 |
const MCInstrInfo &MII, const MCTargetOptions &Options) |
684 |
const MCInstrInfo &MII, const MCTargetOptions &Options) |
| 685 |
: MCTargetAsmParser(Options, STI, MII), UC(Parser), MS(STI) { |
685 |
: MCTargetAsmParser(Options, STI, MII), UC(Parser), MS(STI) { |
| 686 |
MCAsmParserExtension::Initialize(Parser); |
686 |
MCAsmParserExtension::Initialize(Parser); |
| 687 |
|
687 |
|
| 688 |
// Cache the MCRegisterInfo. |
688 |
// Cache the MCRegisterInfo. |
| 689 |
MRI = getContext().getRegisterInfo(); |
689 |
MRI = getContext().getRegisterInfo(); |
| 690 |
|
690 |
|
| 691 |
// Initialize the set of available features. |
691 |
// Initialize the set of available features. |
| 692 |
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); |
692 |
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); |
| 693 |
|
693 |
|
| 694 |
// Add build attributes based on the selected target. |
694 |
// Add build attributes based on the selected target. |
| 695 |
if (AddBuildAttributes) |
695 |
if (AddBuildAttributes) |
| 696 |
getTargetStreamer().emitTargetAttributes(STI); |
696 |
getTargetStreamer().emitTargetAttributes(STI); |
| 697 |
|
697 |
|
| 698 |
// Not in an ITBlock to start with. |
698 |
// Not in an ITBlock to start with. |
| 699 |
ITState.CurPosition = ~0U; |
699 |
ITState.CurPosition = ~0U; |
| 700 |
|
700 |
|
| 701 |
VPTState.CurPosition = ~0U; |
701 |
VPTState.CurPosition = ~0U; |
| 702 |
|
702 |
|
| 703 |
NextSymbolIsThumb = false; |
703 |
NextSymbolIsThumb = false; |
| 704 |
} |
704 |
} |
| 705 |
|
705 |
|
| 706 |
// Implementation of the MCTargetAsmParser interface: |
706 |
// Implementation of the MCTargetAsmParser interface: |
| 707 |
bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc, |
707 |
bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc, |
| 708 |
SMLoc &EndLoc) override; |
708 |
SMLoc &EndLoc) override; |
| 709 |
OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, |
709 |
OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, |
| 710 |
SMLoc &EndLoc) override; |
710 |
SMLoc &EndLoc) override; |
| 711 |
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
711 |
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
| 712 |
SMLoc NameLoc, OperandVector &Operands) override; |
712 |
SMLoc NameLoc, OperandVector &Operands) override; |
| 713 |
bool ParseDirective(AsmToken DirectiveID) override; |
713 |
bool ParseDirective(AsmToken DirectiveID) override; |
| 714 |
|
714 |
|
| 715 |
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, |
715 |
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, |
| 716 |
unsigned Kind) override; |
716 |
unsigned Kind) override; |
| 717 |
unsigned checkTargetMatchPredicate(MCInst &Inst) override; |
717 |
unsigned checkTargetMatchPredicate(MCInst &Inst) override; |
| 718 |
|
718 |
|
| 719 |
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
719 |
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
| 720 |
OperandVector &Operands, MCStreamer &Out, |
720 |
OperandVector &Operands, MCStreamer &Out, |
| 721 |
uint64_t &ErrorInfo, |
721 |
uint64_t &ErrorInfo, |
| 722 |
bool MatchingInlineAsm) override; |
722 |
bool MatchingInlineAsm) override; |
| 723 |
unsigned MatchInstruction(OperandVector &Operands, MCInst &Inst, |
723 |
unsigned MatchInstruction(OperandVector &Operands, MCInst &Inst, |
| 724 |
SmallVectorImpl &NearMisses, |
724 |
SmallVectorImpl &NearMisses, |
| 725 |
bool MatchingInlineAsm, bool &EmitInITBlock, |
725 |
bool MatchingInlineAsm, bool &EmitInITBlock, |
| 726 |
MCStreamer &Out); |
726 |
MCStreamer &Out); |
| 727 |
|
727 |
|
| 728 |
struct NearMissMessage { |
728 |
struct NearMissMessage { |
| 729 |
SMLoc Loc; |
729 |
SMLoc Loc; |
| 730 |
SmallString<128> Message; |
730 |
SmallString<128> Message; |
| 731 |
}; |
731 |
}; |
| 732 |
|
732 |
|
| 733 |
const char *getCustomOperandDiag(ARMMatchResultTy MatchError); |
733 |
const char *getCustomOperandDiag(ARMMatchResultTy MatchError); |
| 734 |
|
734 |
|
| 735 |
void FilterNearMisses(SmallVectorImpl &NearMissesIn, |
735 |
void FilterNearMisses(SmallVectorImpl &NearMissesIn, |
| 736 |
SmallVectorImpl &NearMissesOut, |
736 |
SmallVectorImpl &NearMissesOut, |
| 737 |
SMLoc IDLoc, OperandVector &Operands); |
737 |
SMLoc IDLoc, OperandVector &Operands); |
| 738 |
void ReportNearMisses(SmallVectorImpl &NearMisses, SMLoc IDLoc, |
738 |
void ReportNearMisses(SmallVectorImpl &NearMisses, SMLoc IDLoc, |
| 739 |
OperandVector &Operands); |
739 |
OperandVector &Operands); |
| 740 |
|
740 |
|
| 741 |
void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override; |
741 |
void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override; |
| 742 |
|
742 |
|
| 743 |
void onLabelParsed(MCSymbol *Symbol) override; |
743 |
void onLabelParsed(MCSymbol *Symbol) override; |
| 744 |
}; |
744 |
}; |
| 745 |
|
745 |
|
| 746 |
/// ARMOperand - Instances of this class represent a parsed ARM machine |
746 |
/// ARMOperand - Instances of this class represent a parsed ARM machine |
| 747 |
/// operand. |
747 |
/// operand. |
| 748 |
class ARMOperand : public MCParsedAsmOperand { |
748 |
class ARMOperand : public MCParsedAsmOperand { |
| 749 |
enum KindTy { |
749 |
enum KindTy { |
| 750 |
k_CondCode, |
750 |
k_CondCode, |
| 751 |
k_VPTPred, |
751 |
k_VPTPred, |
| 752 |
k_CCOut, |
752 |
k_CCOut, |
| 753 |
k_ITCondMask, |
753 |
k_ITCondMask, |
| 754 |
k_CoprocNum, |
754 |
k_CoprocNum, |
| 755 |
k_CoprocReg, |
755 |
k_CoprocReg, |
| 756 |
k_CoprocOption, |
756 |
k_CoprocOption, |
| 757 |
k_Immediate, |
757 |
k_Immediate, |
| 758 |
k_MemBarrierOpt, |
758 |
k_MemBarrierOpt, |
| 759 |
k_InstSyncBarrierOpt, |
759 |
k_InstSyncBarrierOpt, |
| 760 |
k_TraceSyncBarrierOpt, |
760 |
k_TraceSyncBarrierOpt, |
| 761 |
k_Memory, |
761 |
k_Memory, |
| 762 |
k_PostIndexRegister, |
762 |
k_PostIndexRegister, |
| 763 |
k_MSRMask, |
763 |
k_MSRMask, |
| 764 |
k_BankedReg, |
764 |
k_BankedReg, |
| 765 |
k_ProcIFlags, |
765 |
k_ProcIFlags, |
| 766 |
k_VectorIndex, |
766 |
k_VectorIndex, |
| 767 |
k_Register, |
767 |
k_Register, |
| 768 |
k_RegisterList, |
768 |
k_RegisterList, |
| 769 |
k_RegisterListWithAPSR, |
769 |
k_RegisterListWithAPSR, |
| 770 |
k_DPRRegisterList, |
770 |
k_DPRRegisterList, |
| 771 |
k_SPRRegisterList, |
771 |
k_SPRRegisterList, |
| 772 |
k_FPSRegisterListWithVPR, |
772 |
k_FPSRegisterListWithVPR, |
| 773 |
k_FPDRegisterListWithVPR, |
773 |
k_FPDRegisterListWithVPR, |
| 774 |
k_VectorList, |
774 |
k_VectorList, |
| 775 |
k_VectorListAllLanes, |
775 |
k_VectorListAllLanes, |
| 776 |
k_VectorListIndexed, |
776 |
k_VectorListIndexed, |
| 777 |
k_ShiftedRegister, |
777 |
k_ShiftedRegister, |
| 778 |
k_ShiftedImmediate, |
778 |
k_ShiftedImmediate, |
| 779 |
k_ShifterImmediate, |
779 |
k_ShifterImmediate, |
| 780 |
k_RotateImmediate, |
780 |
k_RotateImmediate, |
| 781 |
k_ModifiedImmediate, |
781 |
k_ModifiedImmediate, |
| 782 |
k_ConstantPoolImmediate, |
782 |
k_ConstantPoolImmediate, |
| 783 |
k_BitfieldDescriptor, |
783 |
k_BitfieldDescriptor, |
| 784 |
k_Token, |
784 |
k_Token, |
| 785 |
} Kind; |
785 |
} Kind; |
| 786 |
|
786 |
|
| 787 |
SMLoc StartLoc, EndLoc, AlignmentLoc; |
787 |
SMLoc StartLoc, EndLoc, AlignmentLoc; |
| 788 |
SmallVector Registers; |
788 |
SmallVector Registers; |
| 789 |
|
789 |
|
| 790 |
struct CCOp { |
790 |
struct CCOp { |
| 791 |
ARMCC::CondCodes Val; |
791 |
ARMCC::CondCodes Val; |
| 792 |
}; |
792 |
}; |
| 793 |
|
793 |
|
| 794 |
struct VCCOp { |
794 |
struct VCCOp { |
| 795 |
ARMVCC::VPTCodes Val; |
795 |
ARMVCC::VPTCodes Val; |
| 796 |
}; |
796 |
}; |
| 797 |
|
797 |
|
| 798 |
struct CopOp { |
798 |
struct CopOp { |
| 799 |
unsigned Val; |
799 |
unsigned Val; |
| 800 |
}; |
800 |
}; |
| 801 |
|
801 |
|
| 802 |
struct CoprocOptionOp { |
802 |
struct CoprocOptionOp { |
| 803 |
unsigned Val; |
803 |
unsigned Val; |
| 804 |
}; |
804 |
}; |
| 805 |
|
805 |
|
| 806 |
struct ITMaskOp { |
806 |
struct ITMaskOp { |
| 807 |
unsigned Mask:4; |
807 |
unsigned Mask:4; |
| 808 |
}; |
808 |
}; |
| 809 |
|
809 |
|
| 810 |
struct MBOptOp { |
810 |
struct MBOptOp { |
| 811 |
ARM_MB::MemBOpt Val; |
811 |
ARM_MB::MemBOpt Val; |
| 812 |
}; |
812 |
}; |
| 813 |
|
813 |
|
| 814 |
struct ISBOptOp { |
814 |
struct ISBOptOp { |
| 815 |
ARM_ISB::InstSyncBOpt Val; |
815 |
ARM_ISB::InstSyncBOpt Val; |
| 816 |
}; |
816 |
}; |
| 817 |
|
817 |
|
| 818 |
struct TSBOptOp { |
818 |
struct TSBOptOp { |
| 819 |
ARM_TSB::TraceSyncBOpt Val; |
819 |
ARM_TSB::TraceSyncBOpt Val; |
| 820 |
}; |
820 |
}; |
| 821 |
|
821 |
|
| 822 |
struct IFlagsOp { |
822 |
struct IFlagsOp { |
| 823 |
ARM_PROC::IFlags Val; |
823 |
ARM_PROC::IFlags Val; |
| 824 |
}; |
824 |
}; |
| 825 |
|
825 |
|
| 826 |
struct MMaskOp { |
826 |
struct MMaskOp { |
| 827 |
unsigned Val; |
827 |
unsigned Val; |
| 828 |
}; |
828 |
}; |
| 829 |
|
829 |
|
| 830 |
struct BankedRegOp { |
830 |
struct BankedRegOp { |
| 831 |
unsigned Val; |
831 |
unsigned Val; |
| 832 |
}; |
832 |
}; |
| 833 |
|
833 |
|
| 834 |
struct TokOp { |
834 |
struct TokOp { |
| 835 |
const char *Data; |
835 |
const char *Data; |
| 836 |
unsigned Length; |
836 |
unsigned Length; |
| 837 |
}; |
837 |
}; |
| 838 |
|
838 |
|
| 839 |
struct RegOp { |
839 |
struct RegOp { |
| 840 |
unsigned RegNum; |
840 |
unsigned RegNum; |
| 841 |
}; |
841 |
}; |
| 842 |
|
842 |
|
| 843 |
// A vector register list is a sequential list of 1 to 4 registers. |
843 |
// A vector register list is a sequential list of 1 to 4 registers. |
| 844 |
struct VectorListOp { |
844 |
struct VectorListOp { |
| 845 |
unsigned RegNum; |
845 |
unsigned RegNum; |
| 846 |
unsigned Count; |
846 |
unsigned Count; |
| 847 |
unsigned LaneIndex; |
847 |
unsigned LaneIndex; |
| 848 |
bool isDoubleSpaced; |
848 |
bool isDoubleSpaced; |
| 849 |
}; |
849 |
}; |
| 850 |
|
850 |
|
| 851 |
struct VectorIndexOp { |
851 |
struct VectorIndexOp { |
| 852 |
unsigned Val; |
852 |
unsigned Val; |
| 853 |
}; |
853 |
}; |
| 854 |
|
854 |
|
| 855 |
struct ImmOp { |
855 |
struct ImmOp { |
| 856 |
const MCExpr *Val; |
856 |
const MCExpr *Val; |
| 857 |
}; |
857 |
}; |
| 858 |
|
858 |
|
| 859 |
/// Combined record for all forms of ARM address expressions. |
859 |
/// Combined record for all forms of ARM address expressions. |
| 860 |
struct MemoryOp { |
860 |
struct MemoryOp { |
| 861 |
unsigned BaseRegNum; |
861 |
unsigned BaseRegNum; |
| 862 |
// Offset is in OffsetReg or OffsetImm. If both are zero, no offset |
862 |
// Offset is in OffsetReg or OffsetImm. If both are zero, no offset |
| 863 |
// was specified. |
863 |
// was specified. |
| 864 |
const MCExpr *OffsetImm; // Offset immediate value |
864 |
const MCExpr *OffsetImm; // Offset immediate value |
| 865 |
unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL |
865 |
unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL |
| 866 |
ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg |
866 |
ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg |
| 867 |
unsigned ShiftImm; // shift for OffsetReg. |
867 |
unsigned ShiftImm; // shift for OffsetReg. |
| 868 |
unsigned Alignment; // 0 = no alignment specified |
868 |
unsigned Alignment; // 0 = no alignment specified |
| 869 |
// n = alignment in bytes (2, 4, 8, 16, or 32) |
869 |
// n = alignment in bytes (2, 4, 8, 16, or 32) |
| 870 |
unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit) |
870 |
unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit) |
| 871 |
}; |
871 |
}; |
| 872 |
|
872 |
|
| 873 |
struct PostIdxRegOp { |
873 |
struct PostIdxRegOp { |
| 874 |
unsigned RegNum; |
874 |
unsigned RegNum; |
| 875 |
bool isAdd; |
875 |
bool isAdd; |
| 876 |
ARM_AM::ShiftOpc ShiftTy; |
876 |
ARM_AM::ShiftOpc ShiftTy; |
| 877 |
unsigned ShiftImm; |
877 |
unsigned ShiftImm; |
| 878 |
}; |
878 |
}; |
| 879 |
|
879 |
|
| 880 |
struct ShifterImmOp { |
880 |
struct ShifterImmOp { |
| 881 |
bool isASR; |
881 |
bool isASR; |
| 882 |
unsigned Imm; |
882 |
unsigned Imm; |
| 883 |
}; |
883 |
}; |
| 884 |
|
884 |
|
| 885 |
struct RegShiftedRegOp { |
885 |
struct RegShiftedRegOp { |
| 886 |
ARM_AM::ShiftOpc ShiftTy; |
886 |
ARM_AM::ShiftOpc ShiftTy; |
| 887 |
unsigned SrcReg; |
887 |
unsigned SrcReg; |
| 888 |
unsigned ShiftReg; |
888 |
unsigned ShiftReg; |
| 889 |
unsigned ShiftImm; |
889 |
unsigned ShiftImm; |
| 890 |
}; |
890 |
}; |
| 891 |
|
891 |
|
| 892 |
struct RegShiftedImmOp { |
892 |
struct RegShiftedImmOp { |
| 893 |
ARM_AM::ShiftOpc ShiftTy; |
893 |
ARM_AM::ShiftOpc ShiftTy; |
| 894 |
unsigned SrcReg; |
894 |
unsigned SrcReg; |
| 895 |
unsigned ShiftImm; |
895 |
unsigned ShiftImm; |
| 896 |
}; |
896 |
}; |
| 897 |
|
897 |
|
| 898 |
struct RotImmOp { |
898 |
struct RotImmOp { |
| 899 |
unsigned Imm; |
899 |
unsigned Imm; |
| 900 |
}; |
900 |
}; |
| 901 |
|
901 |
|
| 902 |
struct ModImmOp { |
902 |
struct ModImmOp { |
| 903 |
unsigned Bits; |
903 |
unsigned Bits; |
| 904 |
unsigned Rot; |
904 |
unsigned Rot; |
| 905 |
}; |
905 |
}; |
| 906 |
|
906 |
|
| 907 |
struct BitfieldOp { |
907 |
struct BitfieldOp { |
| 908 |
unsigned LSB; |
908 |
unsigned LSB; |
| 909 |
unsigned Width; |
909 |
unsigned Width; |
| 910 |
}; |
910 |
}; |
| 911 |
|
911 |
|
| 912 |
union { |
912 |
union { |
| 913 |
struct CCOp CC; |
913 |
struct CCOp CC; |
| 914 |
struct VCCOp VCC; |
914 |
struct VCCOp VCC; |
| 915 |
struct CopOp Cop; |
915 |
struct CopOp Cop; |
| 916 |
struct CoprocOptionOp CoprocOption; |
916 |
struct CoprocOptionOp CoprocOption; |
| 917 |
struct MBOptOp MBOpt; |
917 |
struct MBOptOp MBOpt; |
| 918 |
struct ISBOptOp ISBOpt; |
918 |
struct ISBOptOp ISBOpt; |
| 919 |
struct TSBOptOp TSBOpt; |
919 |
struct TSBOptOp TSBOpt; |
| 920 |
struct ITMaskOp ITMask; |
920 |
struct ITMaskOp ITMask; |
| 921 |
struct IFlagsOp IFlags; |
921 |
struct IFlagsOp IFlags; |
| 922 |
struct MMaskOp MMask; |
922 |
struct MMaskOp MMask; |
| 923 |
struct BankedRegOp BankedReg; |
923 |
struct BankedRegOp BankedReg; |
| 924 |
struct TokOp Tok; |
924 |
struct TokOp Tok; |
| 925 |
struct RegOp Reg; |
925 |
struct RegOp Reg; |
| 926 |
struct VectorListOp VectorList; |
926 |
struct VectorListOp VectorList; |
| 927 |
struct VectorIndexOp VectorIndex; |
927 |
struct VectorIndexOp VectorIndex; |
| 928 |
struct ImmOp Imm; |
928 |
struct ImmOp Imm; |
| 929 |
struct MemoryOp Memory; |
929 |
struct MemoryOp Memory; |
| 930 |
struct PostIdxRegOp PostIdxReg; |
930 |
struct PostIdxRegOp PostIdxReg; |
| 931 |
struct ShifterImmOp ShifterImm; |
931 |
struct ShifterImmOp ShifterImm; |
| 932 |
struct RegShiftedRegOp RegShiftedReg; |
932 |
struct RegShiftedRegOp RegShiftedReg; |
| 933 |
struct RegShiftedImmOp RegShiftedImm; |
933 |
struct RegShiftedImmOp RegShiftedImm; |
| 934 |
struct RotImmOp RotImm; |
934 |
struct RotImmOp RotImm; |
| 935 |
struct ModImmOp ModImm; |
935 |
struct ModImmOp ModImm; |
| 936 |
struct BitfieldOp Bitfield; |
936 |
struct BitfieldOp Bitfield; |
| 937 |
}; |
937 |
}; |
| 938 |
|
938 |
|
| 939 |
public: |
939 |
public: |
| 940 |
ARMOperand(KindTy K) : Kind(K) {} |
940 |
ARMOperand(KindTy K) : Kind(K) {} |
| 941 |
|
941 |
|
| 942 |
/// getStartLoc - Get the location of the first token of this operand. |
942 |
/// getStartLoc - Get the location of the first token of this operand. |
| 943 |
SMLoc getStartLoc() const override { return StartLoc; } |
943 |
SMLoc getStartLoc() const override { return StartLoc; } |
| 944 |
|
944 |
|
| 945 |
/// getEndLoc - Get the location of the last token of this operand. |
945 |
/// getEndLoc - Get the location of the last token of this operand. |
| 946 |
SMLoc getEndLoc() const override { return EndLoc; } |
946 |
SMLoc getEndLoc() const override { return EndLoc; } |
| 947 |
|
947 |
|
| 948 |
/// getLocRange - Get the range between the first and last token of this |
948 |
/// getLocRange - Get the range between the first and last token of this |
| 949 |
/// operand. |
949 |
/// operand. |
| 950 |
SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); } |
950 |
SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); } |
| 951 |
|
951 |
|
| 952 |
/// getAlignmentLoc - Get the location of the Alignment token of this operand. |
952 |
/// getAlignmentLoc - Get the location of the Alignment token of this operand. |
| 953 |
SMLoc getAlignmentLoc() const { |
953 |
SMLoc getAlignmentLoc() const { |
| 954 |
assert(Kind == k_Memory && "Invalid access!"); |
954 |
assert(Kind == k_Memory && "Invalid access!"); |
| 955 |
return AlignmentLoc; |
955 |
return AlignmentLoc; |
| 956 |
} |
956 |
} |
| 957 |
|
957 |
|
| 958 |
ARMCC::CondCodes getCondCode() const { |
958 |
ARMCC::CondCodes getCondCode() const { |
| 959 |
assert(Kind == k_CondCode && "Invalid access!"); |
959 |
assert(Kind == k_CondCode && "Invalid access!"); |
| 960 |
return CC.Val; |
960 |
return CC.Val; |
| 961 |
} |
961 |
} |
| 962 |
|
962 |
|
| 963 |
ARMVCC::VPTCodes getVPTPred() const { |
963 |
ARMVCC::VPTCodes getVPTPred() const { |
| 964 |
assert(isVPTPred() && "Invalid access!"); |
964 |
assert(isVPTPred() && "Invalid access!"); |
| 965 |
return VCC.Val; |
965 |
return VCC.Val; |
| 966 |
} |
966 |
} |
| 967 |
|
967 |
|
| 968 |
unsigned getCoproc() const { |
968 |
unsigned getCoproc() const { |
| 969 |
assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!"); |
969 |
assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!"); |
| 970 |
return Cop.Val; |
970 |
return Cop.Val; |
| 971 |
} |
971 |
} |
| 972 |
|
972 |
|
| 973 |
StringRef getToken() const { |
973 |
StringRef getToken() const { |
| 974 |
assert(Kind == k_Token && "Invalid access!"); |
974 |
assert(Kind == k_Token && "Invalid access!"); |
| 975 |
return StringRef(Tok.Data, Tok.Length); |
975 |
return StringRef(Tok.Data, Tok.Length); |
| 976 |
} |
976 |
} |
| 977 |
|
977 |
|
| 978 |
unsigned getReg() const override { |
978 |
unsigned getReg() const override { |
| 979 |
assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!"); |
979 |
assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!"); |
| 980 |
return Reg.RegNum; |
980 |
return Reg.RegNum; |
| 981 |
} |
981 |
} |
| 982 |
|
982 |
|
| 983 |
const SmallVectorImpl &getRegList() const { |
983 |
const SmallVectorImpl &getRegList() const { |
| 984 |
assert((Kind == k_RegisterList || Kind == k_RegisterListWithAPSR || |
984 |
assert((Kind == k_RegisterList || Kind == k_RegisterListWithAPSR || |
| 985 |
Kind == k_DPRRegisterList || Kind == k_SPRRegisterList || |
985 |
Kind == k_DPRRegisterList || Kind == k_SPRRegisterList || |
| 986 |
Kind == k_FPSRegisterListWithVPR || |
986 |
Kind == k_FPSRegisterListWithVPR || |
| 987 |
Kind == k_FPDRegisterListWithVPR) && |
987 |
Kind == k_FPDRegisterListWithVPR) && |
| 988 |
"Invalid access!"); |
988 |
"Invalid access!"); |
| 989 |
return Registers; |
989 |
return Registers; |
| 990 |
} |
990 |
} |
| 991 |
|
991 |
|
| 992 |
const MCExpr *getImm() const { |
992 |
const MCExpr *getImm() const { |
| 993 |
assert(isImm() && "Invalid access!"); |
993 |
assert(isImm() && "Invalid access!"); |
| 994 |
return Imm.Val; |
994 |
return Imm.Val; |
| 995 |
} |
995 |
} |
| 996 |
|
996 |
|
| 997 |
const MCExpr *getConstantPoolImm() const { |
997 |
const MCExpr *getConstantPoolImm() const { |
| 998 |
assert(isConstantPoolImm() && "Invalid access!"); |
998 |
assert(isConstantPoolImm() && "Invalid access!"); |
| 999 |
return Imm.Val; |
999 |
return Imm.Val; |
| 1000 |
} |
1000 |
} |
| 1001 |
|
1001 |
|
| 1002 |
unsigned getVectorIndex() const { |
1002 |
unsigned getVectorIndex() const { |
| 1003 |
assert(Kind == k_VectorIndex && "Invalid access!"); |
1003 |
assert(Kind == k_VectorIndex && "Invalid access!"); |
| 1004 |
return VectorIndex.Val; |
1004 |
return VectorIndex.Val; |
| 1005 |
} |
1005 |
} |
| 1006 |
|
1006 |
|
| 1007 |
ARM_MB::MemBOpt getMemBarrierOpt() const { |
1007 |
ARM_MB::MemBOpt getMemBarrierOpt() const { |
| 1008 |
assert(Kind == k_MemBarrierOpt && "Invalid access!"); |
1008 |
assert(Kind == k_MemBarrierOpt && "Invalid access!"); |
| 1009 |
return MBOpt.Val; |
1009 |
return MBOpt.Val; |
| 1010 |
} |
1010 |
} |
| 1011 |
|
1011 |
|
| 1012 |
ARM_ISB::InstSyncBOpt getInstSyncBarrierOpt() const { |
1012 |
ARM_ISB::InstSyncBOpt getInstSyncBarrierOpt() const { |
| 1013 |
assert(Kind == k_InstSyncBarrierOpt && "Invalid access!"); |
1013 |
assert(Kind == k_InstSyncBarrierOpt && "Invalid access!"); |
| 1014 |
return ISBOpt.Val; |
1014 |
return ISBOpt.Val; |
| 1015 |
} |
1015 |
} |
| 1016 |
|
1016 |
|
| 1017 |
ARM_TSB::TraceSyncBOpt getTraceSyncBarrierOpt() const { |
1017 |
ARM_TSB::TraceSyncBOpt getTraceSyncBarrierOpt() const { |
| 1018 |
assert(Kind == k_TraceSyncBarrierOpt && "Invalid access!"); |
1018 |
assert(Kind == k_TraceSyncBarrierOpt && "Invalid access!"); |
| 1019 |
return TSBOpt.Val; |
1019 |
return TSBOpt.Val; |
| 1020 |
} |
1020 |
} |
| 1021 |
|
1021 |
|
| 1022 |
ARM_PROC::IFlags getProcIFlags() const { |
1022 |
ARM_PROC::IFlags getProcIFlags() const { |
| 1023 |
assert(Kind == k_ProcIFlags && "Invalid access!"); |
1023 |
assert(Kind == k_ProcIFlags && "Invalid access!"); |
| 1024 |
return IFlags.Val; |
1024 |
return IFlags.Val; |
| 1025 |
} |
1025 |
} |
| 1026 |
|
1026 |
|
| 1027 |
unsigned getMSRMask() const { |
1027 |
unsigned getMSRMask() const { |
| 1028 |
assert(Kind == k_MSRMask && "Invalid access!"); |
1028 |
assert(Kind == k_MSRMask && "Invalid access!"); |
| 1029 |
return MMask.Val; |
1029 |
return MMask.Val; |
| 1030 |
} |
1030 |
} |
| 1031 |
|
1031 |
|
| 1032 |
unsigned getBankedReg() const { |
1032 |
unsigned getBankedReg() const { |
| 1033 |
assert(Kind == k_BankedReg && "Invalid access!"); |
1033 |
assert(Kind == k_BankedReg && "Invalid access!"); |
| 1034 |
return BankedReg.Val; |
1034 |
return BankedReg.Val; |
| 1035 |
} |
1035 |
} |
| 1036 |
|
1036 |
|
| 1037 |
bool isCoprocNum() const { return Kind == k_CoprocNum; } |
1037 |
bool isCoprocNum() const { return Kind == k_CoprocNum; } |
| 1038 |
bool isCoprocReg() const { return Kind == k_CoprocReg; } |
1038 |
bool isCoprocReg() const { return Kind == k_CoprocReg; } |
| 1039 |
bool isCoprocOption() const { return Kind == k_CoprocOption; } |
1039 |
bool isCoprocOption() const { return Kind == k_CoprocOption; } |
| 1040 |
bool isCondCode() const { return Kind == k_CondCode; } |
1040 |
bool isCondCode() const { return Kind == k_CondCode; } |
| 1041 |
bool isVPTPred() const { return Kind == k_VPTPred; } |
1041 |
bool isVPTPred() const { return Kind == k_VPTPred; } |
| 1042 |
bool isCCOut() const { return Kind == k_CCOut; } |
1042 |
bool isCCOut() const { return Kind == k_CCOut; } |
| 1043 |
bool isITMask() const { return Kind == k_ITCondMask; } |
1043 |
bool isITMask() const { return Kind == k_ITCondMask; } |
| 1044 |
bool isITCondCode() const { return Kind == k_CondCode; } |
1044 |
bool isITCondCode() const { return Kind == k_CondCode; } |
| 1045 |
bool isImm() const override { |
1045 |
bool isImm() const override { |
| 1046 |
return Kind == k_Immediate; |
1046 |
return Kind == k_Immediate; |
| 1047 |
} |
1047 |
} |
| 1048 |
|
1048 |
|
| 1049 |
bool isARMBranchTarget() const { |
1049 |
bool isARMBranchTarget() const { |
| 1050 |
if (!isImm()) return false; |
1050 |
if (!isImm()) return false; |
| 1051 |
|
1051 |
|
| 1052 |
if (const MCConstantExpr *CE = dyn_cast(getImm())) |
1052 |
if (const MCConstantExpr *CE = dyn_cast(getImm())) |
| 1053 |
return CE->getValue() % 4 == 0; |
1053 |
return CE->getValue() % 4 == 0; |
| 1054 |
return true; |
1054 |
return true; |
| 1055 |
} |
1055 |
} |
| 1056 |
|
1056 |
|
| 1057 |
|
1057 |
|
| 1058 |
bool isThumbBranchTarget() const { |
1058 |
bool isThumbBranchTarget() const { |
| 1059 |
if (!isImm()) return false; |
1059 |
if (!isImm()) return false; |
| 1060 |
|
1060 |
|
| 1061 |
if (const MCConstantExpr *CE = dyn_cast(getImm())) |
1061 |
if (const MCConstantExpr *CE = dyn_cast(getImm())) |
| 1062 |
return CE->getValue() % 2 == 0; |
1062 |
return CE->getValue() % 2 == 0; |
| 1063 |
return true; |
1063 |
return true; |
| 1064 |
} |
1064 |
} |
| 1065 |
|
1065 |
|
| 1066 |
// checks whether this operand is an unsigned offset which fits is a field |
1066 |
// checks whether this operand is an unsigned offset which fits is a field |
| 1067 |
// of specified width and scaled by a specific number of bits |
1067 |
// of specified width and scaled by a specific number of bits |
| 1068 |
template |
1068 |
template |
| 1069 |
bool isUnsignedOffset() const { |
1069 |
bool isUnsignedOffset() const { |
| 1070 |
if (!isImm()) return false; |
1070 |
if (!isImm()) return false; |
| 1071 |
if (isa(Imm.Val)) return true; |
1071 |
if (isa(Imm.Val)) return true; |
| 1072 |
if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) { |
1072 |
if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) { |
| 1073 |
int64_t Val = CE->getValue(); |
1073 |
int64_t Val = CE->getValue(); |
| 1074 |
int64_t Align = 1LL << scale; |
1074 |
int64_t Align = 1LL << scale; |
| 1075 |
int64_t Max = Align * ((1LL << width) - 1); |
1075 |
int64_t Max = Align * ((1LL << width) - 1); |
| 1076 |
return ((Val % Align) == 0) && (Val >= 0) && (Val <= Max); |
1076 |
return ((Val % Align) == 0) && (Val >= 0) && (Val <= Max); |
| 1077 |
} |
1077 |
} |
| 1078 |
return false; |
1078 |
return false; |
| 1079 |
} |
1079 |
} |
| 1080 |
|
1080 |
|
| 1081 |
// checks whether this operand is an signed offset which fits is a field |
1081 |
// checks whether this operand is an signed offset which fits is a field |
| 1082 |
// of specified width and scaled by a specific number of bits |
1082 |
// of specified width and scaled by a specific number of bits |
| 1083 |
template |
1083 |
template |
| 1084 |
bool isSignedOffset() const { |
1084 |
bool isSignedOffset() const { |
| 1085 |
if (!isImm()) return false; |
1085 |
if (!isImm()) return false; |
| 1086 |
if (isa(Imm.Val)) return true; |
1086 |
if (isa(Imm.Val)) return true; |
| 1087 |
if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) { |
1087 |
if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) { |
| 1088 |
int64_t Val = CE->getValue(); |
1088 |
int64_t Val = CE->getValue(); |
| 1089 |
int64_t Align = 1LL << scale; |
1089 |
int64_t Align = 1LL << scale; |
| 1090 |
int64_t Max = Align * ((1LL << (width-1)) - 1); |
1090 |
int64_t Max = Align * ((1LL << (width-1)) - 1); |
| 1091 |
int64_t Min = -Align * (1LL << (width-1)); |
1091 |
int64_t Min = -Align * (1LL << (width-1)); |
| 1092 |
return ((Val % Align) == 0) && (Val >= Min) && (Val <= Max); |
1092 |
return ((Val % Align) == 0) && (Val >= Min) && (Val <= Max); |
| 1093 |
} |
1093 |
} |
| 1094 |
return false; |
1094 |
return false; |
| 1095 |
} |
1095 |
} |
| 1096 |
|
1096 |
|
| 1097 |
// checks whether this operand is an offset suitable for the LE / |
1097 |
// checks whether this operand is an offset suitable for the LE / |
| 1098 |
// LETP instructions in Arm v8.1M |
1098 |
// LETP instructions in Arm v8.1M |
| 1099 |
bool isLEOffset() const { |
1099 |
bool isLEOffset() const { |
| 1100 |
if (!isImm()) return false; |
1100 |
if (!isImm()) return false; |
| 1101 |
if (isa(Imm.Val)) return true; |
1101 |
if (isa(Imm.Val)) return true; |
| 1102 |
if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) { |
1102 |
if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) { |
| 1103 |
int64_t Val = CE->getValue(); |
1103 |
int64_t Val = CE->getValue(); |
| 1104 |
return Val < 0 && Val >= -4094 && (Val & 1) == 0; |
1104 |
return Val < 0 && Val >= -4094 && (Val & 1) == 0; |
| 1105 |
} |
1105 |
} |
| 1106 |
return false; |
1106 |
return false; |
| 1107 |
} |
1107 |
} |
| 1108 |
|
1108 |
|
| 1109 |
// checks whether this operand is a memory operand computed as an offset |
1109 |
// checks whether this operand is a memory operand computed as an offset |
| 1110 |
// applied to PC. the offset may have 8 bits of magnitude and is represented |
1110 |
// applied to PC. the offset may have 8 bits of magnitude and is represented |
| 1111 |
// with two bits of shift. textually it may be either [pc, #imm], #imm or |
1111 |
// with two bits of shift. textually it may be either [pc, #imm], #imm or |
| 1112 |
// relocable expression... |
1112 |
// relocable expression... |
| 1113 |
bool isThumbMemPC() const { |
1113 |
bool isThumbMemPC() const { |
| 1114 |
int64_t Val = 0; |
1114 |
int64_t Val = 0; |
| 1115 |
if (isImm()) { |
1115 |
if (isImm()) { |
| 1116 |
if (isa(Imm.Val)) return true; |
1116 |
if (isa(Imm.Val)) return true; |
| 1117 |
const MCConstantExpr *CE = dyn_cast(Imm.Val); |
1117 |
const MCConstantExpr *CE = dyn_cast(Imm.Val); |
| 1118 |
if (!CE) return false; |
1118 |
if (!CE) return false; |
| 1119 |
Val = CE->getValue(); |
1119 |
Val = CE->getValue(); |
| 1120 |
} |
1120 |
} |
| 1121 |
else if (isGPRMem()) { |
1121 |
else if (isGPRMem()) { |
| 1122 |
if(!Memory.OffsetImm || Memory.OffsetRegNum) return false; |
1122 |
if(!Memory.OffsetImm || Memory.OffsetRegNum) return false; |
| 1123 |
if(Memory.BaseRegNum != ARM::PC) return false; |
1123 |
if(Memory.BaseRegNum != ARM::PC) return false; |
| 1124 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
1124 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
| 1125 |
Val = CE->getValue(); |
1125 |
Val = CE->getValue(); |
| 1126 |
else |
1126 |
else |
| 1127 |
return false; |
1127 |
return false; |
| 1128 |
} |
1128 |
} |
| 1129 |
else return false; |
1129 |
else return false; |
| 1130 |
return ((Val % 4) == 0) && (Val >= 0) && (Val <= 1020); |
1130 |
return ((Val % 4) == 0) && (Val >= 0) && (Val <= 1020); |
| 1131 |
} |
1131 |
} |
| 1132 |
|
1132 |
|
| 1133 |
bool isFPImm() const { |
1133 |
bool isFPImm() const { |
| 1134 |
if (!isImm()) return false; |
1134 |
if (!isImm()) return false; |
| 1135 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1135 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1136 |
if (!CE) return false; |
1136 |
if (!CE) return false; |
| 1137 |
int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); |
1137 |
int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); |
| 1138 |
return Val != -1; |
1138 |
return Val != -1; |
| 1139 |
} |
1139 |
} |
| 1140 |
|
1140 |
|
| 1141 |
template |
1141 |
template |
| 1142 |
bool isImmediate() const { |
1142 |
bool isImmediate() const { |
| 1143 |
if (!isImm()) return false; |
1143 |
if (!isImm()) return false; |
| 1144 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1144 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1145 |
if (!CE) return false; |
1145 |
if (!CE) return false; |
| 1146 |
int64_t Value = CE->getValue(); |
1146 |
int64_t Value = CE->getValue(); |
| 1147 |
return Value >= N && Value <= M; |
1147 |
return Value >= N && Value <= M; |
| 1148 |
} |
1148 |
} |
| 1149 |
|
1149 |
|
| 1150 |
template |
1150 |
template |
| 1151 |
bool isImmediateS4() const { |
1151 |
bool isImmediateS4() const { |
| 1152 |
if (!isImm()) return false; |
1152 |
if (!isImm()) return false; |
| 1153 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1153 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1154 |
if (!CE) return false; |
1154 |
if (!CE) return false; |
| 1155 |
int64_t Value = CE->getValue(); |
1155 |
int64_t Value = CE->getValue(); |
| 1156 |
return ((Value & 3) == 0) && Value >= N && Value <= M; |
1156 |
return ((Value & 3) == 0) && Value >= N && Value <= M; |
| 1157 |
} |
1157 |
} |
| 1158 |
template |
1158 |
template |
| 1159 |
bool isImmediateS2() const { |
1159 |
bool isImmediateS2() const { |
| 1160 |
if (!isImm()) return false; |
1160 |
if (!isImm()) return false; |
| 1161 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1161 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1162 |
if (!CE) return false; |
1162 |
if (!CE) return false; |
| 1163 |
int64_t Value = CE->getValue(); |
1163 |
int64_t Value = CE->getValue(); |
| 1164 |
return ((Value & 1) == 0) && Value >= N && Value <= M; |
1164 |
return ((Value & 1) == 0) && Value >= N && Value <= M; |
| 1165 |
} |
1165 |
} |
| 1166 |
bool isFBits16() const { |
1166 |
bool isFBits16() const { |
| 1167 |
return isImmediate<0, 17>(); |
1167 |
return isImmediate<0, 17>(); |
| 1168 |
} |
1168 |
} |
| 1169 |
bool isFBits32() const { |
1169 |
bool isFBits32() const { |
| 1170 |
return isImmediate<1, 33>(); |
1170 |
return isImmediate<1, 33>(); |
| 1171 |
} |
1171 |
} |
| 1172 |
bool isImm8s4() const { |
1172 |
bool isImm8s4() const { |
| 1173 |
return isImmediateS4<-1020, 1020>(); |
1173 |
return isImmediateS4<-1020, 1020>(); |
| 1174 |
} |
1174 |
} |
| 1175 |
bool isImm7s4() const { |
1175 |
bool isImm7s4() const { |
| 1176 |
return isImmediateS4<-508, 508>(); |
1176 |
return isImmediateS4<-508, 508>(); |
| 1177 |
} |
1177 |
} |
| 1178 |
bool isImm7Shift0() const { |
1178 |
bool isImm7Shift0() const { |
| 1179 |
return isImmediate<-127, 127>(); |
1179 |
return isImmediate<-127, 127>(); |
| 1180 |
} |
1180 |
} |
| 1181 |
bool isImm7Shift1() const { |
1181 |
bool isImm7Shift1() const { |
| 1182 |
return isImmediateS2<-255, 255>(); |
1182 |
return isImmediateS2<-255, 255>(); |
| 1183 |
} |
1183 |
} |
| 1184 |
bool isImm7Shift2() const { |
1184 |
bool isImm7Shift2() const { |
| 1185 |
return isImmediateS4<-511, 511>(); |
1185 |
return isImmediateS4<-511, 511>(); |
| 1186 |
} |
1186 |
} |
| 1187 |
bool isImm7() const { |
1187 |
bool isImm7() const { |
| 1188 |
return isImmediate<-127, 127>(); |
1188 |
return isImmediate<-127, 127>(); |
| 1189 |
} |
1189 |
} |
| 1190 |
bool isImm0_1020s4() const { |
1190 |
bool isImm0_1020s4() const { |
| 1191 |
return isImmediateS4<0, 1020>(); |
1191 |
return isImmediateS4<0, 1020>(); |
| 1192 |
} |
1192 |
} |
| 1193 |
bool isImm0_508s4() const { |
1193 |
bool isImm0_508s4() const { |
| 1194 |
return isImmediateS4<0, 508>(); |
1194 |
return isImmediateS4<0, 508>(); |
| 1195 |
} |
1195 |
} |
| 1196 |
bool isImm0_508s4Neg() const { |
1196 |
bool isImm0_508s4Neg() const { |
| 1197 |
if (!isImm()) return false; |
1197 |
if (!isImm()) return false; |
| 1198 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1198 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1199 |
if (!CE) return false; |
1199 |
if (!CE) return false; |
| 1200 |
int64_t Value = -CE->getValue(); |
1200 |
int64_t Value = -CE->getValue(); |
| 1201 |
// explicitly exclude zero. we want that to use the normal 0_508 version. |
1201 |
// explicitly exclude zero. we want that to use the normal 0_508 version. |
| 1202 |
return ((Value & 3) == 0) && Value > 0 && Value <= 508; |
1202 |
return ((Value & 3) == 0) && Value > 0 && Value <= 508; |
| 1203 |
} |
1203 |
} |
| 1204 |
|
1204 |
|
| 1205 |
bool isImm0_4095Neg() const { |
1205 |
bool isImm0_4095Neg() const { |
| 1206 |
if (!isImm()) return false; |
1206 |
if (!isImm()) return false; |
| 1207 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1207 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1208 |
if (!CE) return false; |
1208 |
if (!CE) return false; |
| 1209 |
// isImm0_4095Neg is used with 32-bit immediates only. |
1209 |
// isImm0_4095Neg is used with 32-bit immediates only. |
| 1210 |
// 32-bit immediates are zero extended to 64-bit when parsed, |
1210 |
// 32-bit immediates are zero extended to 64-bit when parsed, |
| 1211 |
// thus simple -CE->getValue() results in a big negative number, |
1211 |
// thus simple -CE->getValue() results in a big negative number, |
| 1212 |
// not a small positive number as intended |
1212 |
// not a small positive number as intended |
| 1213 |
if ((CE->getValue() >> 32) > 0) return false; |
1213 |
if ((CE->getValue() >> 32) > 0) return false; |
| 1214 |
uint32_t Value = -static_cast(CE->getValue()); |
1214 |
uint32_t Value = -static_cast(CE->getValue()); |
| 1215 |
return Value > 0 && Value < 4096; |
1215 |
return Value > 0 && Value < 4096; |
| 1216 |
} |
1216 |
} |
| 1217 |
|
1217 |
|
| 1218 |
bool isImm0_7() const { |
1218 |
bool isImm0_7() const { |
| 1219 |
return isImmediate<0, 7>(); |
1219 |
return isImmediate<0, 7>(); |
| 1220 |
} |
1220 |
} |
| 1221 |
|
1221 |
|
| 1222 |
bool isImm1_16() const { |
1222 |
bool isImm1_16() const { |
| 1223 |
return isImmediate<1, 16>(); |
1223 |
return isImmediate<1, 16>(); |
| 1224 |
} |
1224 |
} |
| 1225 |
|
1225 |
|
| 1226 |
bool isImm1_32() const { |
1226 |
bool isImm1_32() const { |
| 1227 |
return isImmediate<1, 32>(); |
1227 |
return isImmediate<1, 32>(); |
| 1228 |
} |
1228 |
} |
| 1229 |
|
1229 |
|
| 1230 |
bool isImm8_255() const { |
1230 |
bool isImm8_255() const { |
| 1231 |
return isImmediate<8, 255>(); |
1231 |
return isImmediate<8, 255>(); |
| 1232 |
} |
1232 |
} |
| 1233 |
|
1233 |
|
| 1234 |
bool isImm0_255Expr() const { |
1234 |
bool isImm0_255Expr() const { |
| 1235 |
if (!isImm()) |
1235 |
if (!isImm()) |
| 1236 |
return false; |
1236 |
return false; |
| 1237 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1237 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1238 |
// If it's not a constant expression, it'll generate a fixup and be |
1238 |
// If it's not a constant expression, it'll generate a fixup and be |
| 1239 |
// handled later. |
1239 |
// handled later. |
| 1240 |
if (!CE) |
1240 |
if (!CE) |
| 1241 |
return true; |
1241 |
return true; |
| 1242 |
int64_t Value = CE->getValue(); |
1242 |
int64_t Value = CE->getValue(); |
| 1243 |
return isUInt<8>(Value); |
1243 |
return isUInt<8>(Value); |
| 1244 |
} |
1244 |
} |
| 1245 |
|
1245 |
|
| 1246 |
bool isImm256_65535Expr() const { |
1246 |
bool isImm256_65535Expr() const { |
| 1247 |
if (!isImm()) return false; |
1247 |
if (!isImm()) return false; |
| 1248 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1248 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1249 |
// If it's not a constant expression, it'll generate a fixup and be |
1249 |
// If it's not a constant expression, it'll generate a fixup and be |
| 1250 |
// handled later. |
1250 |
// handled later. |
| 1251 |
if (!CE) return true; |
1251 |
if (!CE) return true; |
| 1252 |
int64_t Value = CE->getValue(); |
1252 |
int64_t Value = CE->getValue(); |
| 1253 |
return Value >= 256 && Value < 65536; |
1253 |
return Value >= 256 && Value < 65536; |
| 1254 |
} |
1254 |
} |
| 1255 |
|
1255 |
|
| 1256 |
bool isImm0_65535Expr() const { |
1256 |
bool isImm0_65535Expr() const { |
| 1257 |
if (!isImm()) return false; |
1257 |
if (!isImm()) return false; |
| 1258 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1258 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1259 |
// If it's not a constant expression, it'll generate a fixup and be |
1259 |
// If it's not a constant expression, it'll generate a fixup and be |
| 1260 |
// handled later. |
1260 |
// handled later. |
| 1261 |
if (!CE) return true; |
1261 |
if (!CE) return true; |
| 1262 |
int64_t Value = CE->getValue(); |
1262 |
int64_t Value = CE->getValue(); |
| 1263 |
return Value >= 0 && Value < 65536; |
1263 |
return Value >= 0 && Value < 65536; |
| 1264 |
} |
1264 |
} |
| 1265 |
|
1265 |
|
| 1266 |
bool isImm24bit() const { |
1266 |
bool isImm24bit() const { |
| 1267 |
return isImmediate<0, 0xffffff + 1>(); |
1267 |
return isImmediate<0, 0xffffff + 1>(); |
| 1268 |
} |
1268 |
} |
| 1269 |
|
1269 |
|
| 1270 |
bool isImmThumbSR() const { |
1270 |
bool isImmThumbSR() const { |
| 1271 |
return isImmediate<1, 33>(); |
1271 |
return isImmediate<1, 33>(); |
| 1272 |
} |
1272 |
} |
| 1273 |
|
1273 |
|
| 1274 |
bool isPKHLSLImm() const { |
1274 |
bool isPKHLSLImm() const { |
| 1275 |
return isImmediate<0, 32>(); |
1275 |
return isImmediate<0, 32>(); |
| 1276 |
} |
1276 |
} |
| 1277 |
|
1277 |
|
| 1278 |
bool isPKHASRImm() const { |
1278 |
bool isPKHASRImm() const { |
| 1279 |
return isImmediate<0, 33>(); |
1279 |
return isImmediate<0, 33>(); |
| 1280 |
} |
1280 |
} |
| 1281 |
|
1281 |
|
| 1282 |
bool isAdrLabel() const { |
1282 |
bool isAdrLabel() const { |
| 1283 |
// If we have an immediate that's not a constant, treat it as a label |
1283 |
// If we have an immediate that's not a constant, treat it as a label |
| 1284 |
// reference needing a fixup. |
1284 |
// reference needing a fixup. |
| 1285 |
if (isImm() && !isa(getImm())) |
1285 |
if (isImm() && !isa(getImm())) |
| 1286 |
return true; |
1286 |
return true; |
| 1287 |
|
1287 |
|
| 1288 |
// If it is a constant, it must fit into a modified immediate encoding. |
1288 |
// If it is a constant, it must fit into a modified immediate encoding. |
| 1289 |
if (!isImm()) return false; |
1289 |
if (!isImm()) return false; |
| 1290 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1290 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1291 |
if (!CE) return false; |
1291 |
if (!CE) return false; |
| 1292 |
int64_t Value = CE->getValue(); |
1292 |
int64_t Value = CE->getValue(); |
| 1293 |
return (ARM_AM::getSOImmVal(Value) != -1 || |
1293 |
return (ARM_AM::getSOImmVal(Value) != -1 || |
| 1294 |
ARM_AM::getSOImmVal(-Value) != -1); |
1294 |
ARM_AM::getSOImmVal(-Value) != -1); |
| 1295 |
} |
1295 |
} |
| 1296 |
|
1296 |
|
| 1297 |
bool isT2SOImm() const { |
1297 |
bool isT2SOImm() const { |
| 1298 |
// If we have an immediate that's not a constant, treat it as an expression |
1298 |
// If we have an immediate that's not a constant, treat it as an expression |
| 1299 |
// needing a fixup. |
1299 |
// needing a fixup. |
| 1300 |
if (isImm() && !isa(getImm())) { |
1300 |
if (isImm() && !isa(getImm())) { |
| 1301 |
// We want to avoid matching :upper16: and :lower16: as we want these |
1301 |
// We want to avoid matching :upper16: and :lower16: as we want these |
| 1302 |
// expressions to match in isImm0_65535Expr() |
1302 |
// expressions to match in isImm0_65535Expr() |
| 1303 |
const ARMMCExpr *ARM16Expr = dyn_cast(getImm()); |
1303 |
const ARMMCExpr *ARM16Expr = dyn_cast(getImm()); |
| 1304 |
return (!ARM16Expr || (ARM16Expr->getKind() != ARMMCExpr::VK_ARM_HI16 && |
1304 |
return (!ARM16Expr || (ARM16Expr->getKind() != ARMMCExpr::VK_ARM_HI16 && |
| 1305 |
ARM16Expr->getKind() != ARMMCExpr::VK_ARM_LO16)); |
1305 |
ARM16Expr->getKind() != ARMMCExpr::VK_ARM_LO16)); |
| 1306 |
} |
1306 |
} |
| 1307 |
if (!isImm()) return false; |
1307 |
if (!isImm()) return false; |
| 1308 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1308 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1309 |
if (!CE) return false; |
1309 |
if (!CE) return false; |
| 1310 |
int64_t Value = CE->getValue(); |
1310 |
int64_t Value = CE->getValue(); |
| 1311 |
return ARM_AM::getT2SOImmVal(Value) != -1; |
1311 |
return ARM_AM::getT2SOImmVal(Value) != -1; |
| 1312 |
} |
1312 |
} |
| 1313 |
|
1313 |
|
| 1314 |
bool isT2SOImmNot() const { |
1314 |
bool isT2SOImmNot() const { |
| 1315 |
if (!isImm()) return false; |
1315 |
if (!isImm()) return false; |
| 1316 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1316 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1317 |
if (!CE) return false; |
1317 |
if (!CE) return false; |
| 1318 |
int64_t Value = CE->getValue(); |
1318 |
int64_t Value = CE->getValue(); |
| 1319 |
return ARM_AM::getT2SOImmVal(Value) == -1 && |
1319 |
return ARM_AM::getT2SOImmVal(Value) == -1 && |
| 1320 |
ARM_AM::getT2SOImmVal(~Value) != -1; |
1320 |
ARM_AM::getT2SOImmVal(~Value) != -1; |
| 1321 |
} |
1321 |
} |
| 1322 |
|
1322 |
|
| 1323 |
bool isT2SOImmNeg() const { |
1323 |
bool isT2SOImmNeg() const { |
| 1324 |
if (!isImm()) return false; |
1324 |
if (!isImm()) return false; |
| 1325 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1325 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1326 |
if (!CE) return false; |
1326 |
if (!CE) return false; |
| 1327 |
int64_t Value = CE->getValue(); |
1327 |
int64_t Value = CE->getValue(); |
| 1328 |
// Only use this when not representable as a plain so_imm. |
1328 |
// Only use this when not representable as a plain so_imm. |
| 1329 |
return ARM_AM::getT2SOImmVal(Value) == -1 && |
1329 |
return ARM_AM::getT2SOImmVal(Value) == -1 && |
| 1330 |
ARM_AM::getT2SOImmVal(-Value) != -1; |
1330 |
ARM_AM::getT2SOImmVal(-Value) != -1; |
| 1331 |
} |
1331 |
} |
| 1332 |
|
1332 |
|
| 1333 |
bool isSetEndImm() const { |
1333 |
bool isSetEndImm() const { |
| 1334 |
if (!isImm()) return false; |
1334 |
if (!isImm()) return false; |
| 1335 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1335 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1336 |
if (!CE) return false; |
1336 |
if (!CE) return false; |
| 1337 |
int64_t Value = CE->getValue(); |
1337 |
int64_t Value = CE->getValue(); |
| 1338 |
return Value == 1 || Value == 0; |
1338 |
return Value == 1 || Value == 0; |
| 1339 |
} |
1339 |
} |
| 1340 |
|
1340 |
|
| 1341 |
bool isReg() const override { return Kind == k_Register; } |
1341 |
bool isReg() const override { return Kind == k_Register; } |
| 1342 |
bool isRegList() const { return Kind == k_RegisterList; } |
1342 |
bool isRegList() const { return Kind == k_RegisterList; } |
| 1343 |
bool isRegListWithAPSR() const { |
1343 |
bool isRegListWithAPSR() const { |
| 1344 |
return Kind == k_RegisterListWithAPSR || Kind == k_RegisterList; |
1344 |
return Kind == k_RegisterListWithAPSR || Kind == k_RegisterList; |
| 1345 |
} |
1345 |
} |
| 1346 |
bool isDPRRegList() const { return Kind == k_DPRRegisterList; } |
1346 |
bool isDPRRegList() const { return Kind == k_DPRRegisterList; } |
| 1347 |
bool isSPRRegList() const { return Kind == k_SPRRegisterList; } |
1347 |
bool isSPRRegList() const { return Kind == k_SPRRegisterList; } |
| 1348 |
bool isFPSRegListWithVPR() const { return Kind == k_FPSRegisterListWithVPR; } |
1348 |
bool isFPSRegListWithVPR() const { return Kind == k_FPSRegisterListWithVPR; } |
| 1349 |
bool isFPDRegListWithVPR() const { return Kind == k_FPDRegisterListWithVPR; } |
1349 |
bool isFPDRegListWithVPR() const { return Kind == k_FPDRegisterListWithVPR; } |
| 1350 |
bool isToken() const override { return Kind == k_Token; } |
1350 |
bool isToken() const override { return Kind == k_Token; } |
| 1351 |
bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; } |
1351 |
bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; } |
| 1352 |
bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; } |
1352 |
bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; } |
| 1353 |
bool isTraceSyncBarrierOpt() const { return Kind == k_TraceSyncBarrierOpt; } |
1353 |
bool isTraceSyncBarrierOpt() const { return Kind == k_TraceSyncBarrierOpt; } |
| 1354 |
bool isMem() const override { |
1354 |
bool isMem() const override { |
| 1355 |
return isGPRMem() || isMVEMem(); |
1355 |
return isGPRMem() || isMVEMem(); |
| 1356 |
} |
1356 |
} |
| 1357 |
bool isMVEMem() const { |
1357 |
bool isMVEMem() const { |
| 1358 |
if (Kind != k_Memory) |
1358 |
if (Kind != k_Memory) |
| 1359 |
return false; |
1359 |
return false; |
| 1360 |
if (Memory.BaseRegNum && |
1360 |
if (Memory.BaseRegNum && |
| 1361 |
!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Memory.BaseRegNum) && |
1361 |
!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Memory.BaseRegNum) && |
| 1362 |
!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(Memory.BaseRegNum)) |
1362 |
!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(Memory.BaseRegNum)) |
| 1363 |
return false; |
1363 |
return false; |
| 1364 |
if (Memory.OffsetRegNum && |
1364 |
if (Memory.OffsetRegNum && |
| 1365 |
!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains( |
1365 |
!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains( |
| 1366 |
Memory.OffsetRegNum)) |
1366 |
Memory.OffsetRegNum)) |
| 1367 |
return false; |
1367 |
return false; |
| 1368 |
return true; |
1368 |
return true; |
| 1369 |
} |
1369 |
} |
| 1370 |
bool isGPRMem() const { |
1370 |
bool isGPRMem() const { |
| 1371 |
if (Kind != k_Memory) |
1371 |
if (Kind != k_Memory) |
| 1372 |
return false; |
1372 |
return false; |
| 1373 |
if (Memory.BaseRegNum && |
1373 |
if (Memory.BaseRegNum && |
| 1374 |
!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Memory.BaseRegNum)) |
1374 |
!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Memory.BaseRegNum)) |
| 1375 |
return false; |
1375 |
return false; |
| 1376 |
if (Memory.OffsetRegNum && |
1376 |
if (Memory.OffsetRegNum && |
| 1377 |
!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Memory.OffsetRegNum)) |
1377 |
!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Memory.OffsetRegNum)) |
| 1378 |
return false; |
1378 |
return false; |
| 1379 |
return true; |
1379 |
return true; |
| 1380 |
} |
1380 |
} |
| 1381 |
bool isShifterImm() const { return Kind == k_ShifterImmediate; } |
1381 |
bool isShifterImm() const { return Kind == k_ShifterImmediate; } |
| 1382 |
bool isRegShiftedReg() const { |
1382 |
bool isRegShiftedReg() const { |
| 1383 |
return Kind == k_ShiftedRegister && |
1383 |
return Kind == k_ShiftedRegister && |
| 1384 |
ARMMCRegisterClasses[ARM::GPRRegClassID].contains( |
1384 |
ARMMCRegisterClasses[ARM::GPRRegClassID].contains( |
| 1385 |
RegShiftedReg.SrcReg) && |
1385 |
RegShiftedReg.SrcReg) && |
| 1386 |
ARMMCRegisterClasses[ARM::GPRRegClassID].contains( |
1386 |
ARMMCRegisterClasses[ARM::GPRRegClassID].contains( |
| 1387 |
RegShiftedReg.ShiftReg); |
1387 |
RegShiftedReg.ShiftReg); |
| 1388 |
} |
1388 |
} |
| 1389 |
bool isRegShiftedImm() const { |
1389 |
bool isRegShiftedImm() const { |
| 1390 |
return Kind == k_ShiftedImmediate && |
1390 |
return Kind == k_ShiftedImmediate && |
| 1391 |
ARMMCRegisterClasses[ARM::GPRRegClassID].contains( |
1391 |
ARMMCRegisterClasses[ARM::GPRRegClassID].contains( |
| 1392 |
RegShiftedImm.SrcReg); |
1392 |
RegShiftedImm.SrcReg); |
| 1393 |
} |
1393 |
} |
| 1394 |
bool isRotImm() const { return Kind == k_RotateImmediate; } |
1394 |
bool isRotImm() const { return Kind == k_RotateImmediate; } |
| 1395 |
|
1395 |
|
| 1396 |
template |
1396 |
template |
| 1397 |
bool isPowerTwoInRange() const { |
1397 |
bool isPowerTwoInRange() const { |
| 1398 |
if (!isImm()) return false; |
1398 |
if (!isImm()) return false; |
| 1399 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1399 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1400 |
if (!CE) return false; |
1400 |
if (!CE) return false; |
| 1401 |
int64_t Value = CE->getValue(); |
1401 |
int64_t Value = CE->getValue(); |
| 1402 |
return Value > 0 && llvm::popcount((uint64_t)Value) == 1 && Value >= Min && |
1402 |
return Value > 0 && llvm::popcount((uint64_t)Value) == 1 && Value >= Min && |
| 1403 |
Value <= Max; |
1403 |
Value <= Max; |
| 1404 |
} |
1404 |
} |
| 1405 |
bool isModImm() const { return Kind == k_ModifiedImmediate; } |
1405 |
bool isModImm() const { return Kind == k_ModifiedImmediate; } |
| 1406 |
|
1406 |
|
| 1407 |
bool isModImmNot() const { |
1407 |
bool isModImmNot() const { |
| 1408 |
if (!isImm()) return false; |
1408 |
if (!isImm()) return false; |
| 1409 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1409 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1410 |
if (!CE) return false; |
1410 |
if (!CE) return false; |
| 1411 |
int64_t Value = CE->getValue(); |
1411 |
int64_t Value = CE->getValue(); |
| 1412 |
return ARM_AM::getSOImmVal(~Value) != -1; |
1412 |
return ARM_AM::getSOImmVal(~Value) != -1; |
| 1413 |
} |
1413 |
} |
| 1414 |
|
1414 |
|
| 1415 |
bool isModImmNeg() const { |
1415 |
bool isModImmNeg() const { |
| 1416 |
if (!isImm()) return false; |
1416 |
if (!isImm()) return false; |
| 1417 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1417 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1418 |
if (!CE) return false; |
1418 |
if (!CE) return false; |
| 1419 |
int64_t Value = CE->getValue(); |
1419 |
int64_t Value = CE->getValue(); |
| 1420 |
return ARM_AM::getSOImmVal(Value) == -1 && |
1420 |
return ARM_AM::getSOImmVal(Value) == -1 && |
| 1421 |
ARM_AM::getSOImmVal(-Value) != -1; |
1421 |
ARM_AM::getSOImmVal(-Value) != -1; |
| 1422 |
} |
1422 |
} |
| 1423 |
|
1423 |
|
| 1424 |
bool isThumbModImmNeg1_7() const { |
1424 |
bool isThumbModImmNeg1_7() const { |
| 1425 |
if (!isImm()) return false; |
1425 |
if (!isImm()) return false; |
| 1426 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1426 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1427 |
if (!CE) return false; |
1427 |
if (!CE) return false; |
| 1428 |
int32_t Value = -(int32_t)CE->getValue(); |
1428 |
int32_t Value = -(int32_t)CE->getValue(); |
| 1429 |
return 0 < Value && Value < 8; |
1429 |
return 0 < Value && Value < 8; |
| 1430 |
} |
1430 |
} |
| 1431 |
|
1431 |
|
| 1432 |
bool isThumbModImmNeg8_255() const { |
1432 |
bool isThumbModImmNeg8_255() const { |
| 1433 |
if (!isImm()) return false; |
1433 |
if (!isImm()) return false; |
| 1434 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1434 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1435 |
if (!CE) return false; |
1435 |
if (!CE) return false; |
| 1436 |
int32_t Value = -(int32_t)CE->getValue(); |
1436 |
int32_t Value = -(int32_t)CE->getValue(); |
| 1437 |
return 7 < Value && Value < 256; |
1437 |
return 7 < Value && Value < 256; |
| 1438 |
} |
1438 |
} |
| 1439 |
|
1439 |
|
| 1440 |
bool isConstantPoolImm() const { return Kind == k_ConstantPoolImmediate; } |
1440 |
bool isConstantPoolImm() const { return Kind == k_ConstantPoolImmediate; } |
| 1441 |
bool isBitfield() const { return Kind == k_BitfieldDescriptor; } |
1441 |
bool isBitfield() const { return Kind == k_BitfieldDescriptor; } |
| 1442 |
bool isPostIdxRegShifted() const { |
1442 |
bool isPostIdxRegShifted() const { |
| 1443 |
return Kind == k_PostIndexRegister && |
1443 |
return Kind == k_PostIndexRegister && |
| 1444 |
ARMMCRegisterClasses[ARM::GPRRegClassID].contains(PostIdxReg.RegNum); |
1444 |
ARMMCRegisterClasses[ARM::GPRRegClassID].contains(PostIdxReg.RegNum); |
| 1445 |
} |
1445 |
} |
| 1446 |
bool isPostIdxReg() const { |
1446 |
bool isPostIdxReg() const { |
| 1447 |
return isPostIdxRegShifted() && PostIdxReg.ShiftTy == ARM_AM::no_shift; |
1447 |
return isPostIdxRegShifted() && PostIdxReg.ShiftTy == ARM_AM::no_shift; |
| 1448 |
} |
1448 |
} |
| 1449 |
bool isMemNoOffset(bool alignOK = false, unsigned Alignment = 0) const { |
1449 |
bool isMemNoOffset(bool alignOK = false, unsigned Alignment = 0) const { |
| 1450 |
if (!isGPRMem()) |
1450 |
if (!isGPRMem()) |
| 1451 |
return false; |
1451 |
return false; |
| 1452 |
// No offset of any kind. |
1452 |
// No offset of any kind. |
| 1453 |
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr && |
1453 |
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr && |
| 1454 |
(alignOK || Memory.Alignment == Alignment); |
1454 |
(alignOK || Memory.Alignment == Alignment); |
| 1455 |
} |
1455 |
} |
| 1456 |
bool isMemNoOffsetT2(bool alignOK = false, unsigned Alignment = 0) const { |
1456 |
bool isMemNoOffsetT2(bool alignOK = false, unsigned Alignment = 0) const { |
| 1457 |
if (!isGPRMem()) |
1457 |
if (!isGPRMem()) |
| 1458 |
return false; |
1458 |
return false; |
| 1459 |
|
1459 |
|
| 1460 |
if (!ARMMCRegisterClasses[ARM::GPRnopcRegClassID].contains( |
1460 |
if (!ARMMCRegisterClasses[ARM::GPRnopcRegClassID].contains( |
| 1461 |
Memory.BaseRegNum)) |
1461 |
Memory.BaseRegNum)) |
| 1462 |
return false; |
1462 |
return false; |
| 1463 |
|
1463 |
|
| 1464 |
// No offset of any kind. |
1464 |
// No offset of any kind. |
| 1465 |
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr && |
1465 |
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr && |
| 1466 |
(alignOK || Memory.Alignment == Alignment); |
1466 |
(alignOK || Memory.Alignment == Alignment); |
| 1467 |
} |
1467 |
} |
| 1468 |
bool isMemNoOffsetT2NoSp(bool alignOK = false, unsigned Alignment = 0) const { |
1468 |
bool isMemNoOffsetT2NoSp(bool alignOK = false, unsigned Alignment = 0) const { |
| 1469 |
if (!isGPRMem()) |
1469 |
if (!isGPRMem()) |
| 1470 |
return false; |
1470 |
return false; |
| 1471 |
|
1471 |
|
| 1472 |
if (!ARMMCRegisterClasses[ARM::rGPRRegClassID].contains( |
1472 |
if (!ARMMCRegisterClasses[ARM::rGPRRegClassID].contains( |
| 1473 |
Memory.BaseRegNum)) |
1473 |
Memory.BaseRegNum)) |
| 1474 |
return false; |
1474 |
return false; |
| 1475 |
|
1475 |
|
| 1476 |
// No offset of any kind. |
1476 |
// No offset of any kind. |
| 1477 |
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr && |
1477 |
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr && |
| 1478 |
(alignOK || Memory.Alignment == Alignment); |
1478 |
(alignOK || Memory.Alignment == Alignment); |
| 1479 |
} |
1479 |
} |
| 1480 |
bool isMemNoOffsetT(bool alignOK = false, unsigned Alignment = 0) const { |
1480 |
bool isMemNoOffsetT(bool alignOK = false, unsigned Alignment = 0) const { |
| 1481 |
if (!isGPRMem()) |
1481 |
if (!isGPRMem()) |
| 1482 |
return false; |
1482 |
return false; |
| 1483 |
|
1483 |
|
| 1484 |
if (!ARMMCRegisterClasses[ARM::tGPRRegClassID].contains( |
1484 |
if (!ARMMCRegisterClasses[ARM::tGPRRegClassID].contains( |
| 1485 |
Memory.BaseRegNum)) |
1485 |
Memory.BaseRegNum)) |
| 1486 |
return false; |
1486 |
return false; |
| 1487 |
|
1487 |
|
| 1488 |
// No offset of any kind. |
1488 |
// No offset of any kind. |
| 1489 |
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr && |
1489 |
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr && |
| 1490 |
(alignOK || Memory.Alignment == Alignment); |
1490 |
(alignOK || Memory.Alignment == Alignment); |
| 1491 |
} |
1491 |
} |
| 1492 |
bool isMemPCRelImm12() const { |
1492 |
bool isMemPCRelImm12() const { |
| 1493 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
1493 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
| 1494 |
return false; |
1494 |
return false; |
| 1495 |
// Base register must be PC. |
1495 |
// Base register must be PC. |
| 1496 |
if (Memory.BaseRegNum != ARM::PC) |
1496 |
if (Memory.BaseRegNum != ARM::PC) |
| 1497 |
return false; |
1497 |
return false; |
| 1498 |
// Immediate offset in range [-4095, 4095]. |
1498 |
// Immediate offset in range [-4095, 4095]. |
| 1499 |
if (!Memory.OffsetImm) return true; |
1499 |
if (!Memory.OffsetImm) return true; |
| 1500 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1500 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1501 |
int64_t Val = CE->getValue(); |
1501 |
int64_t Val = CE->getValue(); |
| 1502 |
return (Val > -4096 && Val < 4096) || |
1502 |
return (Val > -4096 && Val < 4096) || |
| 1503 |
(Val == std::numeric_limits::min()); |
1503 |
(Val == std::numeric_limits::min()); |
| 1504 |
} |
1504 |
} |
| 1505 |
return false; |
1505 |
return false; |
| 1506 |
} |
1506 |
} |
| 1507 |
|
1507 |
|
| 1508 |
bool isAlignedMemory() const { |
1508 |
bool isAlignedMemory() const { |
| 1509 |
return isMemNoOffset(true); |
1509 |
return isMemNoOffset(true); |
| 1510 |
} |
1510 |
} |
| 1511 |
|
1511 |
|
| 1512 |
bool isAlignedMemoryNone() const { |
1512 |
bool isAlignedMemoryNone() const { |
| 1513 |
return isMemNoOffset(false, 0); |
1513 |
return isMemNoOffset(false, 0); |
| 1514 |
} |
1514 |
} |
| 1515 |
|
1515 |
|
| 1516 |
bool isDupAlignedMemoryNone() const { |
1516 |
bool isDupAlignedMemoryNone() const { |
| 1517 |
return isMemNoOffset(false, 0); |
1517 |
return isMemNoOffset(false, 0); |
| 1518 |
} |
1518 |
} |
| 1519 |
|
1519 |
|
| 1520 |
bool isAlignedMemory16() const { |
1520 |
bool isAlignedMemory16() const { |
| 1521 |
if (isMemNoOffset(false, 2)) // alignment in bytes for 16-bits is 2. |
1521 |
if (isMemNoOffset(false, 2)) // alignment in bytes for 16-bits is 2. |
| 1522 |
return true; |
1522 |
return true; |
| 1523 |
return isMemNoOffset(false, 0); |
1523 |
return isMemNoOffset(false, 0); |
| 1524 |
} |
1524 |
} |
| 1525 |
|
1525 |
|
| 1526 |
bool isDupAlignedMemory16() const { |
1526 |
bool isDupAlignedMemory16() const { |
| 1527 |
if (isMemNoOffset(false, 2)) // alignment in bytes for 16-bits is 2. |
1527 |
if (isMemNoOffset(false, 2)) // alignment in bytes for 16-bits is 2. |
| 1528 |
return true; |
1528 |
return true; |
| 1529 |
return isMemNoOffset(false, 0); |
1529 |
return isMemNoOffset(false, 0); |
| 1530 |
} |
1530 |
} |
| 1531 |
|
1531 |
|
| 1532 |
bool isAlignedMemory32() const { |
1532 |
bool isAlignedMemory32() const { |
| 1533 |
if (isMemNoOffset(false, 4)) // alignment in bytes for 32-bits is 4. |
1533 |
if (isMemNoOffset(false, 4)) // alignment in bytes for 32-bits is 4. |
| 1534 |
return true; |
1534 |
return true; |
| 1535 |
return isMemNoOffset(false, 0); |
1535 |
return isMemNoOffset(false, 0); |
| 1536 |
} |
1536 |
} |
| 1537 |
|
1537 |
|
| 1538 |
bool isDupAlignedMemory32() const { |
1538 |
bool isDupAlignedMemory32() const { |
| 1539 |
if (isMemNoOffset(false, 4)) // alignment in bytes for 32-bits is 4. |
1539 |
if (isMemNoOffset(false, 4)) // alignment in bytes for 32-bits is 4. |
| 1540 |
return true; |
1540 |
return true; |
| 1541 |
return isMemNoOffset(false, 0); |
1541 |
return isMemNoOffset(false, 0); |
| 1542 |
} |
1542 |
} |
| 1543 |
|
1543 |
|
| 1544 |
bool isAlignedMemory64() const { |
1544 |
bool isAlignedMemory64() const { |
| 1545 |
if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8. |
1545 |
if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8. |
| 1546 |
return true; |
1546 |
return true; |
| 1547 |
return isMemNoOffset(false, 0); |
1547 |
return isMemNoOffset(false, 0); |
| 1548 |
} |
1548 |
} |
| 1549 |
|
1549 |
|
| 1550 |
bool isDupAlignedMemory64() const { |
1550 |
bool isDupAlignedMemory64() const { |
| 1551 |
if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8. |
1551 |
if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8. |
| 1552 |
return true; |
1552 |
return true; |
| 1553 |
return isMemNoOffset(false, 0); |
1553 |
return isMemNoOffset(false, 0); |
| 1554 |
} |
1554 |
} |
| 1555 |
|
1555 |
|
| 1556 |
bool isAlignedMemory64or128() const { |
1556 |
bool isAlignedMemory64or128() const { |
| 1557 |
if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8. |
1557 |
if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8. |
| 1558 |
return true; |
1558 |
return true; |
| 1559 |
if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16. |
1559 |
if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16. |
| 1560 |
return true; |
1560 |
return true; |
| 1561 |
return isMemNoOffset(false, 0); |
1561 |
return isMemNoOffset(false, 0); |
| 1562 |
} |
1562 |
} |
| 1563 |
|
1563 |
|
| 1564 |
bool isDupAlignedMemory64or128() const { |
1564 |
bool isDupAlignedMemory64or128() const { |
| 1565 |
if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8. |
1565 |
if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8. |
| 1566 |
return true; |
1566 |
return true; |
| 1567 |
if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16. |
1567 |
if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16. |
| 1568 |
return true; |
1568 |
return true; |
| 1569 |
return isMemNoOffset(false, 0); |
1569 |
return isMemNoOffset(false, 0); |
| 1570 |
} |
1570 |
} |
| 1571 |
|
1571 |
|
| 1572 |
bool isAlignedMemory64or128or256() const { |
1572 |
bool isAlignedMemory64or128or256() const { |
| 1573 |
if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8. |
1573 |
if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8. |
| 1574 |
return true; |
1574 |
return true; |
| 1575 |
if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16. |
1575 |
if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16. |
| 1576 |
return true; |
1576 |
return true; |
| 1577 |
if (isMemNoOffset(false, 32)) // alignment in bytes for 256-bits is 32. |
1577 |
if (isMemNoOffset(false, 32)) // alignment in bytes for 256-bits is 32. |
| 1578 |
return true; |
1578 |
return true; |
| 1579 |
return isMemNoOffset(false, 0); |
1579 |
return isMemNoOffset(false, 0); |
| 1580 |
} |
1580 |
} |
| 1581 |
|
1581 |
|
| 1582 |
bool isAddrMode2() const { |
1582 |
bool isAddrMode2() const { |
| 1583 |
if (!isGPRMem() || Memory.Alignment != 0) return false; |
1583 |
if (!isGPRMem() || Memory.Alignment != 0) return false; |
| 1584 |
// Check for register offset. |
1584 |
// Check for register offset. |
| 1585 |
if (Memory.OffsetRegNum) return true; |
1585 |
if (Memory.OffsetRegNum) return true; |
| 1586 |
// Immediate offset in range [-4095, 4095]. |
1586 |
// Immediate offset in range [-4095, 4095]. |
| 1587 |
if (!Memory.OffsetImm) return true; |
1587 |
if (!Memory.OffsetImm) return true; |
| 1588 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1588 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1589 |
int64_t Val = CE->getValue(); |
1589 |
int64_t Val = CE->getValue(); |
| 1590 |
return Val > -4096 && Val < 4096; |
1590 |
return Val > -4096 && Val < 4096; |
| 1591 |
} |
1591 |
} |
| 1592 |
return false; |
1592 |
return false; |
| 1593 |
} |
1593 |
} |
| 1594 |
|
1594 |
|
| 1595 |
bool isAM2OffsetImm() const { |
1595 |
bool isAM2OffsetImm() const { |
| 1596 |
if (!isImm()) return false; |
1596 |
if (!isImm()) return false; |
| 1597 |
// Immediate offset in range [-4095, 4095]. |
1597 |
// Immediate offset in range [-4095, 4095]. |
| 1598 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1598 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1599 |
if (!CE) return false; |
1599 |
if (!CE) return false; |
| 1600 |
int64_t Val = CE->getValue(); |
1600 |
int64_t Val = CE->getValue(); |
| 1601 |
return (Val == std::numeric_limits::min()) || |
1601 |
return (Val == std::numeric_limits::min()) || |
| 1602 |
(Val > -4096 && Val < 4096); |
1602 |
(Val > -4096 && Val < 4096); |
| 1603 |
} |
1603 |
} |
| 1604 |
|
1604 |
|
| 1605 |
bool isAddrMode3() const { |
1605 |
bool isAddrMode3() const { |
| 1606 |
// If we have an immediate that's not a constant, treat it as a label |
1606 |
// If we have an immediate that's not a constant, treat it as a label |
| 1607 |
// reference needing a fixup. If it is a constant, it's something else |
1607 |
// reference needing a fixup. If it is a constant, it's something else |
| 1608 |
// and we reject it. |
1608 |
// and we reject it. |
| 1609 |
if (isImm() && !isa(getImm())) |
1609 |
if (isImm() && !isa(getImm())) |
| 1610 |
return true; |
1610 |
return true; |
| 1611 |
if (!isGPRMem() || Memory.Alignment != 0) return false; |
1611 |
if (!isGPRMem() || Memory.Alignment != 0) return false; |
| 1612 |
// No shifts are legal for AM3. |
1612 |
// No shifts are legal for AM3. |
| 1613 |
if (Memory.ShiftType != ARM_AM::no_shift) return false; |
1613 |
if (Memory.ShiftType != ARM_AM::no_shift) return false; |
| 1614 |
// Check for register offset. |
1614 |
// Check for register offset. |
| 1615 |
if (Memory.OffsetRegNum) return true; |
1615 |
if (Memory.OffsetRegNum) return true; |
| 1616 |
// Immediate offset in range [-255, 255]. |
1616 |
// Immediate offset in range [-255, 255]. |
| 1617 |
if (!Memory.OffsetImm) return true; |
1617 |
if (!Memory.OffsetImm) return true; |
| 1618 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1618 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1619 |
int64_t Val = CE->getValue(); |
1619 |
int64_t Val = CE->getValue(); |
| 1620 |
// The #-0 offset is encoded as std::numeric_limits::min(), and |
1620 |
// The #-0 offset is encoded as std::numeric_limits::min(), and |
| 1621 |
// we have to check for this too. |
1621 |
// we have to check for this too. |
| 1622 |
return (Val > -256 && Val < 256) || |
1622 |
return (Val > -256 && Val < 256) || |
| 1623 |
Val == std::numeric_limits::min(); |
1623 |
Val == std::numeric_limits::min(); |
| 1624 |
} |
1624 |
} |
| 1625 |
return false; |
1625 |
return false; |
| 1626 |
} |
1626 |
} |
| 1627 |
|
1627 |
|
| 1628 |
bool isAM3Offset() const { |
1628 |
bool isAM3Offset() const { |
| 1629 |
if (isPostIdxReg()) |
1629 |
if (isPostIdxReg()) |
| 1630 |
return true; |
1630 |
return true; |
| 1631 |
if (!isImm()) |
1631 |
if (!isImm()) |
| 1632 |
return false; |
1632 |
return false; |
| 1633 |
// Immediate offset in range [-255, 255]. |
1633 |
// Immediate offset in range [-255, 255]. |
| 1634 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1634 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1635 |
if (!CE) return false; |
1635 |
if (!CE) return false; |
| 1636 |
int64_t Val = CE->getValue(); |
1636 |
int64_t Val = CE->getValue(); |
| 1637 |
// Special case, #-0 is std::numeric_limits::min(). |
1637 |
// Special case, #-0 is std::numeric_limits::min(). |
| 1638 |
return (Val > -256 && Val < 256) || |
1638 |
return (Val > -256 && Val < 256) || |
| 1639 |
Val == std::numeric_limits::min(); |
1639 |
Val == std::numeric_limits::min(); |
| 1640 |
} |
1640 |
} |
| 1641 |
|
1641 |
|
| 1642 |
bool isAddrMode5() const { |
1642 |
bool isAddrMode5() const { |
| 1643 |
// If we have an immediate that's not a constant, treat it as a label |
1643 |
// If we have an immediate that's not a constant, treat it as a label |
| 1644 |
// reference needing a fixup. If it is a constant, it's something else |
1644 |
// reference needing a fixup. If it is a constant, it's something else |
| 1645 |
// and we reject it. |
1645 |
// and we reject it. |
| 1646 |
if (isImm() && !isa(getImm())) |
1646 |
if (isImm() && !isa(getImm())) |
| 1647 |
return true; |
1647 |
return true; |
| 1648 |
if (!isGPRMem() || Memory.Alignment != 0) return false; |
1648 |
if (!isGPRMem() || Memory.Alignment != 0) return false; |
| 1649 |
// Check for register offset. |
1649 |
// Check for register offset. |
| 1650 |
if (Memory.OffsetRegNum) return false; |
1650 |
if (Memory.OffsetRegNum) return false; |
| 1651 |
// Immediate offset in range [-1020, 1020] and a multiple of 4. |
1651 |
// Immediate offset in range [-1020, 1020] and a multiple of 4. |
| 1652 |
if (!Memory.OffsetImm) return true; |
1652 |
if (!Memory.OffsetImm) return true; |
| 1653 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1653 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1654 |
int64_t Val = CE->getValue(); |
1654 |
int64_t Val = CE->getValue(); |
| 1655 |
return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) || |
1655 |
return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) || |
| 1656 |
Val == std::numeric_limits::min(); |
1656 |
Val == std::numeric_limits::min(); |
| 1657 |
} |
1657 |
} |
| 1658 |
return false; |
1658 |
return false; |
| 1659 |
} |
1659 |
} |
| 1660 |
|
1660 |
|
| 1661 |
bool isAddrMode5FP16() const { |
1661 |
bool isAddrMode5FP16() const { |
| 1662 |
// If we have an immediate that's not a constant, treat it as a label |
1662 |
// If we have an immediate that's not a constant, treat it as a label |
| 1663 |
// reference needing a fixup. If it is a constant, it's something else |
1663 |
// reference needing a fixup. If it is a constant, it's something else |
| 1664 |
// and we reject it. |
1664 |
// and we reject it. |
| 1665 |
if (isImm() && !isa(getImm())) |
1665 |
if (isImm() && !isa(getImm())) |
| 1666 |
return true; |
1666 |
return true; |
| 1667 |
if (!isGPRMem() || Memory.Alignment != 0) return false; |
1667 |
if (!isGPRMem() || Memory.Alignment != 0) return false; |
| 1668 |
// Check for register offset. |
1668 |
// Check for register offset. |
| 1669 |
if (Memory.OffsetRegNum) return false; |
1669 |
if (Memory.OffsetRegNum) return false; |
| 1670 |
// Immediate offset in range [-510, 510] and a multiple of 2. |
1670 |
// Immediate offset in range [-510, 510] and a multiple of 2. |
| 1671 |
if (!Memory.OffsetImm) return true; |
1671 |
if (!Memory.OffsetImm) return true; |
| 1672 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1672 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1673 |
int64_t Val = CE->getValue(); |
1673 |
int64_t Val = CE->getValue(); |
| 1674 |
return (Val >= -510 && Val <= 510 && ((Val & 1) == 0)) || |
1674 |
return (Val >= -510 && Val <= 510 && ((Val & 1) == 0)) || |
| 1675 |
Val == std::numeric_limits::min(); |
1675 |
Val == std::numeric_limits::min(); |
| 1676 |
} |
1676 |
} |
| 1677 |
return false; |
1677 |
return false; |
| 1678 |
} |
1678 |
} |
| 1679 |
|
1679 |
|
| 1680 |
bool isMemTBB() const { |
1680 |
bool isMemTBB() const { |
| 1681 |
if (!isGPRMem() || !Memory.OffsetRegNum || Memory.isNegative || |
1681 |
if (!isGPRMem() || !Memory.OffsetRegNum || Memory.isNegative || |
| 1682 |
Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) |
1682 |
Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) |
| 1683 |
return false; |
1683 |
return false; |
| 1684 |
return true; |
1684 |
return true; |
| 1685 |
} |
1685 |
} |
| 1686 |
|
1686 |
|
| 1687 |
bool isMemTBH() const { |
1687 |
bool isMemTBH() const { |
| 1688 |
if (!isGPRMem() || !Memory.OffsetRegNum || Memory.isNegative || |
1688 |
if (!isGPRMem() || !Memory.OffsetRegNum || Memory.isNegative || |
| 1689 |
Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 || |
1689 |
Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 || |
| 1690 |
Memory.Alignment != 0 ) |
1690 |
Memory.Alignment != 0 ) |
| 1691 |
return false; |
1691 |
return false; |
| 1692 |
return true; |
1692 |
return true; |
| 1693 |
} |
1693 |
} |
| 1694 |
|
1694 |
|
| 1695 |
bool isMemRegOffset() const { |
1695 |
bool isMemRegOffset() const { |
| 1696 |
if (!isGPRMem() || !Memory.OffsetRegNum || Memory.Alignment != 0) |
1696 |
if (!isGPRMem() || !Memory.OffsetRegNum || Memory.Alignment != 0) |
| 1697 |
return false; |
1697 |
return false; |
| 1698 |
return true; |
1698 |
return true; |
| 1699 |
} |
1699 |
} |
| 1700 |
|
1700 |
|
| 1701 |
bool isT2MemRegOffset() const { |
1701 |
bool isT2MemRegOffset() const { |
| 1702 |
if (!isGPRMem() || !Memory.OffsetRegNum || Memory.isNegative || |
1702 |
if (!isGPRMem() || !Memory.OffsetRegNum || Memory.isNegative || |
| 1703 |
Memory.Alignment != 0 || Memory.BaseRegNum == ARM::PC) |
1703 |
Memory.Alignment != 0 || Memory.BaseRegNum == ARM::PC) |
| 1704 |
return false; |
1704 |
return false; |
| 1705 |
// Only lsl #{0, 1, 2, 3} allowed. |
1705 |
// Only lsl #{0, 1, 2, 3} allowed. |
| 1706 |
if (Memory.ShiftType == ARM_AM::no_shift) |
1706 |
if (Memory.ShiftType == ARM_AM::no_shift) |
| 1707 |
return true; |
1707 |
return true; |
| 1708 |
if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3) |
1708 |
if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3) |
| 1709 |
return false; |
1709 |
return false; |
| 1710 |
return true; |
1710 |
return true; |
| 1711 |
} |
1711 |
} |
| 1712 |
|
1712 |
|
| 1713 |
bool isMemThumbRR() const { |
1713 |
bool isMemThumbRR() const { |
| 1714 |
// Thumb reg+reg addressing is simple. Just two registers, a base and |
1714 |
// Thumb reg+reg addressing is simple. Just two registers, a base and |
| 1715 |
// an offset. No shifts, negations or any other complicating factors. |
1715 |
// an offset. No shifts, negations or any other complicating factors. |
| 1716 |
if (!isGPRMem() || !Memory.OffsetRegNum || Memory.isNegative || |
1716 |
if (!isGPRMem() || !Memory.OffsetRegNum || Memory.isNegative || |
| 1717 |
Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) |
1717 |
Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) |
| 1718 |
return false; |
1718 |
return false; |
| 1719 |
return isARMLowRegister(Memory.BaseRegNum) && |
1719 |
return isARMLowRegister(Memory.BaseRegNum) && |
| 1720 |
(!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum)); |
1720 |
(!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum)); |
| 1721 |
} |
1721 |
} |
| 1722 |
|
1722 |
|
| 1723 |
bool isMemThumbRIs4() const { |
1723 |
bool isMemThumbRIs4() const { |
| 1724 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || |
1724 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || |
| 1725 |
!isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) |
1725 |
!isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) |
| 1726 |
return false; |
1726 |
return false; |
| 1727 |
// Immediate offset, multiple of 4 in range [0, 124]. |
1727 |
// Immediate offset, multiple of 4 in range [0, 124]. |
| 1728 |
if (!Memory.OffsetImm) return true; |
1728 |
if (!Memory.OffsetImm) return true; |
| 1729 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1729 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1730 |
int64_t Val = CE->getValue(); |
1730 |
int64_t Val = CE->getValue(); |
| 1731 |
return Val >= 0 && Val <= 124 && (Val % 4) == 0; |
1731 |
return Val >= 0 && Val <= 124 && (Val % 4) == 0; |
| 1732 |
} |
1732 |
} |
| 1733 |
return false; |
1733 |
return false; |
| 1734 |
} |
1734 |
} |
| 1735 |
|
1735 |
|
| 1736 |
bool isMemThumbRIs2() const { |
1736 |
bool isMemThumbRIs2() const { |
| 1737 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || |
1737 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || |
| 1738 |
!isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) |
1738 |
!isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) |
| 1739 |
return false; |
1739 |
return false; |
| 1740 |
// Immediate offset, multiple of 4 in range [0, 62]. |
1740 |
// Immediate offset, multiple of 4 in range [0, 62]. |
| 1741 |
if (!Memory.OffsetImm) return true; |
1741 |
if (!Memory.OffsetImm) return true; |
| 1742 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1742 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1743 |
int64_t Val = CE->getValue(); |
1743 |
int64_t Val = CE->getValue(); |
| 1744 |
return Val >= 0 && Val <= 62 && (Val % 2) == 0; |
1744 |
return Val >= 0 && Val <= 62 && (Val % 2) == 0; |
| 1745 |
} |
1745 |
} |
| 1746 |
return false; |
1746 |
return false; |
| 1747 |
} |
1747 |
} |
| 1748 |
|
1748 |
|
| 1749 |
bool isMemThumbRIs1() const { |
1749 |
bool isMemThumbRIs1() const { |
| 1750 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || |
1750 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || |
| 1751 |
!isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) |
1751 |
!isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) |
| 1752 |
return false; |
1752 |
return false; |
| 1753 |
// Immediate offset in range [0, 31]. |
1753 |
// Immediate offset in range [0, 31]. |
| 1754 |
if (!Memory.OffsetImm) return true; |
1754 |
if (!Memory.OffsetImm) return true; |
| 1755 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1755 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1756 |
int64_t Val = CE->getValue(); |
1756 |
int64_t Val = CE->getValue(); |
| 1757 |
return Val >= 0 && Val <= 31; |
1757 |
return Val >= 0 && Val <= 31; |
| 1758 |
} |
1758 |
} |
| 1759 |
return false; |
1759 |
return false; |
| 1760 |
} |
1760 |
} |
| 1761 |
|
1761 |
|
| 1762 |
bool isMemThumbSPI() const { |
1762 |
bool isMemThumbSPI() const { |
| 1763 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || |
1763 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || |
| 1764 |
Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0) |
1764 |
Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0) |
| 1765 |
return false; |
1765 |
return false; |
| 1766 |
// Immediate offset, multiple of 4 in range [0, 1020]. |
1766 |
// Immediate offset, multiple of 4 in range [0, 1020]. |
| 1767 |
if (!Memory.OffsetImm) return true; |
1767 |
if (!Memory.OffsetImm) return true; |
| 1768 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1768 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1769 |
int64_t Val = CE->getValue(); |
1769 |
int64_t Val = CE->getValue(); |
| 1770 |
return Val >= 0 && Val <= 1020 && (Val % 4) == 0; |
1770 |
return Val >= 0 && Val <= 1020 && (Val % 4) == 0; |
| 1771 |
} |
1771 |
} |
| 1772 |
return false; |
1772 |
return false; |
| 1773 |
} |
1773 |
} |
| 1774 |
|
1774 |
|
| 1775 |
bool isMemImm8s4Offset() const { |
1775 |
bool isMemImm8s4Offset() const { |
| 1776 |
// If we have an immediate that's not a constant, treat it as a label |
1776 |
// If we have an immediate that's not a constant, treat it as a label |
| 1777 |
// reference needing a fixup. If it is a constant, it's something else |
1777 |
// reference needing a fixup. If it is a constant, it's something else |
| 1778 |
// and we reject it. |
1778 |
// and we reject it. |
| 1779 |
if (isImm() && !isa(getImm())) |
1779 |
if (isImm() && !isa(getImm())) |
| 1780 |
return true; |
1780 |
return true; |
| 1781 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
1781 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
| 1782 |
return false; |
1782 |
return false; |
| 1783 |
// Immediate offset a multiple of 4 in range [-1020, 1020]. |
1783 |
// Immediate offset a multiple of 4 in range [-1020, 1020]. |
| 1784 |
if (!Memory.OffsetImm) return true; |
1784 |
if (!Memory.OffsetImm) return true; |
| 1785 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1785 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1786 |
int64_t Val = CE->getValue(); |
1786 |
int64_t Val = CE->getValue(); |
| 1787 |
// Special case, #-0 is std::numeric_limits::min(). |
1787 |
// Special case, #-0 is std::numeric_limits::min(). |
| 1788 |
return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) || |
1788 |
return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) || |
| 1789 |
Val == std::numeric_limits::min(); |
1789 |
Val == std::numeric_limits::min(); |
| 1790 |
} |
1790 |
} |
| 1791 |
return false; |
1791 |
return false; |
| 1792 |
} |
1792 |
} |
| 1793 |
|
1793 |
|
| 1794 |
bool isMemImm7s4Offset() const { |
1794 |
bool isMemImm7s4Offset() const { |
| 1795 |
// If we have an immediate that's not a constant, treat it as a label |
1795 |
// If we have an immediate that's not a constant, treat it as a label |
| 1796 |
// reference needing a fixup. If it is a constant, it's something else |
1796 |
// reference needing a fixup. If it is a constant, it's something else |
| 1797 |
// and we reject it. |
1797 |
// and we reject it. |
| 1798 |
if (isImm() && !isa(getImm())) |
1798 |
if (isImm() && !isa(getImm())) |
| 1799 |
return true; |
1799 |
return true; |
| 1800 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0 || |
1800 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0 || |
| 1801 |
!ARMMCRegisterClasses[ARM::GPRnopcRegClassID].contains( |
1801 |
!ARMMCRegisterClasses[ARM::GPRnopcRegClassID].contains( |
| 1802 |
Memory.BaseRegNum)) |
1802 |
Memory.BaseRegNum)) |
| 1803 |
return false; |
1803 |
return false; |
| 1804 |
// Immediate offset a multiple of 4 in range [-508, 508]. |
1804 |
// Immediate offset a multiple of 4 in range [-508, 508]. |
| 1805 |
if (!Memory.OffsetImm) return true; |
1805 |
if (!Memory.OffsetImm) return true; |
| 1806 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1806 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1807 |
int64_t Val = CE->getValue(); |
1807 |
int64_t Val = CE->getValue(); |
| 1808 |
// Special case, #-0 is INT32_MIN. |
1808 |
// Special case, #-0 is INT32_MIN. |
| 1809 |
return (Val >= -508 && Val <= 508 && (Val & 3) == 0) || Val == INT32_MIN; |
1809 |
return (Val >= -508 && Val <= 508 && (Val & 3) == 0) || Val == INT32_MIN; |
| 1810 |
} |
1810 |
} |
| 1811 |
return false; |
1811 |
return false; |
| 1812 |
} |
1812 |
} |
| 1813 |
|
1813 |
|
| 1814 |
bool isMemImm0_1020s4Offset() const { |
1814 |
bool isMemImm0_1020s4Offset() const { |
| 1815 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
1815 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
| 1816 |
return false; |
1816 |
return false; |
| 1817 |
// Immediate offset a multiple of 4 in range [0, 1020]. |
1817 |
// Immediate offset a multiple of 4 in range [0, 1020]. |
| 1818 |
if (!Memory.OffsetImm) return true; |
1818 |
if (!Memory.OffsetImm) return true; |
| 1819 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1819 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1820 |
int64_t Val = CE->getValue(); |
1820 |
int64_t Val = CE->getValue(); |
| 1821 |
return Val >= 0 && Val <= 1020 && (Val & 3) == 0; |
1821 |
return Val >= 0 && Val <= 1020 && (Val & 3) == 0; |
| 1822 |
} |
1822 |
} |
| 1823 |
return false; |
1823 |
return false; |
| 1824 |
} |
1824 |
} |
| 1825 |
|
1825 |
|
| 1826 |
bool isMemImm8Offset() const { |
1826 |
bool isMemImm8Offset() const { |
| 1827 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
1827 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
| 1828 |
return false; |
1828 |
return false; |
| 1829 |
// Base reg of PC isn't allowed for these encodings. |
1829 |
// Base reg of PC isn't allowed for these encodings. |
| 1830 |
if (Memory.BaseRegNum == ARM::PC) return false; |
1830 |
if (Memory.BaseRegNum == ARM::PC) return false; |
| 1831 |
// Immediate offset in range [-255, 255]. |
1831 |
// Immediate offset in range [-255, 255]. |
| 1832 |
if (!Memory.OffsetImm) return true; |
1832 |
if (!Memory.OffsetImm) return true; |
| 1833 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1833 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1834 |
int64_t Val = CE->getValue(); |
1834 |
int64_t Val = CE->getValue(); |
| 1835 |
return (Val == std::numeric_limits::min()) || |
1835 |
return (Val == std::numeric_limits::min()) || |
| 1836 |
(Val > -256 && Val < 256); |
1836 |
(Val > -256 && Val < 256); |
| 1837 |
} |
1837 |
} |
| 1838 |
return false; |
1838 |
return false; |
| 1839 |
} |
1839 |
} |
| 1840 |
|
1840 |
|
| 1841 |
template |
1841 |
template |
| 1842 |
bool isMemImm7ShiftedOffset() const { |
1842 |
bool isMemImm7ShiftedOffset() const { |
| 1843 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0 || |
1843 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0 || |
| 1844 |
!ARMMCRegisterClasses[RegClassID].contains(Memory.BaseRegNum)) |
1844 |
!ARMMCRegisterClasses[RegClassID].contains(Memory.BaseRegNum)) |
| 1845 |
return false; |
1845 |
return false; |
| 1846 |
|
1846 |
|
| 1847 |
// Expect an immediate offset equal to an element of the range |
1847 |
// Expect an immediate offset equal to an element of the range |
| 1848 |
// [-127, 127], shifted left by Bits. |
1848 |
// [-127, 127], shifted left by Bits. |
| 1849 |
|
1849 |
|
| 1850 |
if (!Memory.OffsetImm) return true; |
1850 |
if (!Memory.OffsetImm) return true; |
| 1851 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1851 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1852 |
int64_t Val = CE->getValue(); |
1852 |
int64_t Val = CE->getValue(); |
| 1853 |
|
1853 |
|
| 1854 |
// INT32_MIN is a special-case value (indicating the encoding with |
1854 |
// INT32_MIN is a special-case value (indicating the encoding with |
| 1855 |
// zero offset and the subtract bit set) |
1855 |
// zero offset and the subtract bit set) |
| 1856 |
if (Val == INT32_MIN) |
1856 |
if (Val == INT32_MIN) |
| 1857 |
return true; |
1857 |
return true; |
| 1858 |
|
1858 |
|
| 1859 |
unsigned Divisor = 1U << Bits; |
1859 |
unsigned Divisor = 1U << Bits; |
| 1860 |
|
1860 |
|
| 1861 |
// Check that the low bits are zero |
1861 |
// Check that the low bits are zero |
| 1862 |
if (Val % Divisor != 0) |
1862 |
if (Val % Divisor != 0) |
| 1863 |
return false; |
1863 |
return false; |
| 1864 |
|
1864 |
|
| 1865 |
// Check that the remaining offset is within range. |
1865 |
// Check that the remaining offset is within range. |
| 1866 |
Val /= Divisor; |
1866 |
Val /= Divisor; |
| 1867 |
return (Val >= -127 && Val <= 127); |
1867 |
return (Val >= -127 && Val <= 127); |
| 1868 |
} |
1868 |
} |
| 1869 |
return false; |
1869 |
return false; |
| 1870 |
} |
1870 |
} |
| 1871 |
|
1871 |
|
| 1872 |
template bool isMemRegRQOffset() const { |
1872 |
template bool isMemRegRQOffset() const { |
| 1873 |
if (!isMVEMem() || Memory.OffsetImm != nullptr || Memory.Alignment != 0) |
1873 |
if (!isMVEMem() || Memory.OffsetImm != nullptr || Memory.Alignment != 0) |
| 1874 |
return false; |
1874 |
return false; |
| 1875 |
|
1875 |
|
| 1876 |
if (!ARMMCRegisterClasses[ARM::GPRnopcRegClassID].contains( |
1876 |
if (!ARMMCRegisterClasses[ARM::GPRnopcRegClassID].contains( |
| 1877 |
Memory.BaseRegNum)) |
1877 |
Memory.BaseRegNum)) |
| 1878 |
return false; |
1878 |
return false; |
| 1879 |
if (!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains( |
1879 |
if (!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains( |
| 1880 |
Memory.OffsetRegNum)) |
1880 |
Memory.OffsetRegNum)) |
| 1881 |
return false; |
1881 |
return false; |
| 1882 |
|
1882 |
|
| 1883 |
if (shift == 0 && Memory.ShiftType != ARM_AM::no_shift) |
1883 |
if (shift == 0 && Memory.ShiftType != ARM_AM::no_shift) |
| 1884 |
return false; |
1884 |
return false; |
| 1885 |
|
1885 |
|
| 1886 |
if (shift > 0 && |
1886 |
if (shift > 0 && |
| 1887 |
(Memory.ShiftType != ARM_AM::uxtw || Memory.ShiftImm != shift)) |
1887 |
(Memory.ShiftType != ARM_AM::uxtw || Memory.ShiftImm != shift)) |
| 1888 |
return false; |
1888 |
return false; |
| 1889 |
|
1889 |
|
| 1890 |
return true; |
1890 |
return true; |
| 1891 |
} |
1891 |
} |
| 1892 |
|
1892 |
|
| 1893 |
template bool isMemRegQOffset() const { |
1893 |
template bool isMemRegQOffset() const { |
| 1894 |
if (!isMVEMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
1894 |
if (!isMVEMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
| 1895 |
return false; |
1895 |
return false; |
| 1896 |
|
1896 |
|
| 1897 |
if (!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains( |
1897 |
if (!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains( |
| 1898 |
Memory.BaseRegNum)) |
1898 |
Memory.BaseRegNum)) |
| 1899 |
return false; |
1899 |
return false; |
| 1900 |
|
1900 |
|
| 1901 |
if (!Memory.OffsetImm) |
1901 |
if (!Memory.OffsetImm) |
| 1902 |
return true; |
1902 |
return true; |
| 1903 |
static_assert(shift < 56, |
1903 |
static_assert(shift < 56, |
| 1904 |
"Such that we dont shift by a value higher than 62"); |
1904 |
"Such that we dont shift by a value higher than 62"); |
| 1905 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1905 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1906 |
int64_t Val = CE->getValue(); |
1906 |
int64_t Val = CE->getValue(); |
| 1907 |
|
1907 |
|
| 1908 |
// The value must be a multiple of (1 << shift) |
1908 |
// The value must be a multiple of (1 << shift) |
| 1909 |
if ((Val & ((1U << shift) - 1)) != 0) |
1909 |
if ((Val & ((1U << shift) - 1)) != 0) |
| 1910 |
return false; |
1910 |
return false; |
| 1911 |
|
1911 |
|
| 1912 |
// And be in the right range, depending on the amount that it is shifted |
1912 |
// And be in the right range, depending on the amount that it is shifted |
| 1913 |
// by. Shift 0, is equal to 7 unsigned bits, the sign bit is set |
1913 |
// by. Shift 0, is equal to 7 unsigned bits, the sign bit is set |
| 1914 |
// separately. |
1914 |
// separately. |
| 1915 |
int64_t Range = (1U << (7 + shift)) - 1; |
1915 |
int64_t Range = (1U << (7 + shift)) - 1; |
| 1916 |
return (Val == INT32_MIN) || (Val > -Range && Val < Range); |
1916 |
return (Val == INT32_MIN) || (Val > -Range && Val < Range); |
| 1917 |
} |
1917 |
} |
| 1918 |
return false; |
1918 |
return false; |
| 1919 |
} |
1919 |
} |
| 1920 |
|
1920 |
|
| 1921 |
bool isMemPosImm8Offset() const { |
1921 |
bool isMemPosImm8Offset() const { |
| 1922 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
1922 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
| 1923 |
return false; |
1923 |
return false; |
| 1924 |
// Immediate offset in range [0, 255]. |
1924 |
// Immediate offset in range [0, 255]. |
| 1925 |
if (!Memory.OffsetImm) return true; |
1925 |
if (!Memory.OffsetImm) return true; |
| 1926 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1926 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1927 |
int64_t Val = CE->getValue(); |
1927 |
int64_t Val = CE->getValue(); |
| 1928 |
return Val >= 0 && Val < 256; |
1928 |
return Val >= 0 && Val < 256; |
| 1929 |
} |
1929 |
} |
| 1930 |
return false; |
1930 |
return false; |
| 1931 |
} |
1931 |
} |
| 1932 |
|
1932 |
|
| 1933 |
bool isMemNegImm8Offset() const { |
1933 |
bool isMemNegImm8Offset() const { |
| 1934 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
1934 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
| 1935 |
return false; |
1935 |
return false; |
| 1936 |
// Base reg of PC isn't allowed for these encodings. |
1936 |
// Base reg of PC isn't allowed for these encodings. |
| 1937 |
if (Memory.BaseRegNum == ARM::PC) return false; |
1937 |
if (Memory.BaseRegNum == ARM::PC) return false; |
| 1938 |
// Immediate offset in range [-255, -1]. |
1938 |
// Immediate offset in range [-255, -1]. |
| 1939 |
if (!Memory.OffsetImm) return false; |
1939 |
if (!Memory.OffsetImm) return false; |
| 1940 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1940 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1941 |
int64_t Val = CE->getValue(); |
1941 |
int64_t Val = CE->getValue(); |
| 1942 |
return (Val == std::numeric_limits::min()) || |
1942 |
return (Val == std::numeric_limits::min()) || |
| 1943 |
(Val > -256 && Val < 0); |
1943 |
(Val > -256 && Val < 0); |
| 1944 |
} |
1944 |
} |
| 1945 |
return false; |
1945 |
return false; |
| 1946 |
} |
1946 |
} |
| 1947 |
|
1947 |
|
| 1948 |
bool isMemUImm12Offset() const { |
1948 |
bool isMemUImm12Offset() const { |
| 1949 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
1949 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
| 1950 |
return false; |
1950 |
return false; |
| 1951 |
// Immediate offset in range [0, 4095]. |
1951 |
// Immediate offset in range [0, 4095]. |
| 1952 |
if (!Memory.OffsetImm) return true; |
1952 |
if (!Memory.OffsetImm) return true; |
| 1953 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1953 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1954 |
int64_t Val = CE->getValue(); |
1954 |
int64_t Val = CE->getValue(); |
| 1955 |
return (Val >= 0 && Val < 4096); |
1955 |
return (Val >= 0 && Val < 4096); |
| 1956 |
} |
1956 |
} |
| 1957 |
return false; |
1957 |
return false; |
| 1958 |
} |
1958 |
} |
| 1959 |
|
1959 |
|
| 1960 |
bool isMemImm12Offset() const { |
1960 |
bool isMemImm12Offset() const { |
| 1961 |
// If we have an immediate that's not a constant, treat it as a label |
1961 |
// If we have an immediate that's not a constant, treat it as a label |
| 1962 |
// reference needing a fixup. If it is a constant, it's something else |
1962 |
// reference needing a fixup. If it is a constant, it's something else |
| 1963 |
// and we reject it. |
1963 |
// and we reject it. |
| 1964 |
|
1964 |
|
| 1965 |
if (isImm() && !isa(getImm())) |
1965 |
if (isImm() && !isa(getImm())) |
| 1966 |
return true; |
1966 |
return true; |
| 1967 |
|
1967 |
|
| 1968 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
1968 |
if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) |
| 1969 |
return false; |
1969 |
return false; |
| 1970 |
// Immediate offset in range [-4095, 4095]. |
1970 |
// Immediate offset in range [-4095, 4095]. |
| 1971 |
if (!Memory.OffsetImm) return true; |
1971 |
if (!Memory.OffsetImm) return true; |
| 1972 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
1972 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 1973 |
int64_t Val = CE->getValue(); |
1973 |
int64_t Val = CE->getValue(); |
| 1974 |
return (Val > -4096 && Val < 4096) || |
1974 |
return (Val > -4096 && Val < 4096) || |
| 1975 |
(Val == std::numeric_limits::min()); |
1975 |
(Val == std::numeric_limits::min()); |
| 1976 |
} |
1976 |
} |
| 1977 |
// If we have an immediate that's not a constant, treat it as a |
1977 |
// If we have an immediate that's not a constant, treat it as a |
| 1978 |
// symbolic expression needing a fixup. |
1978 |
// symbolic expression needing a fixup. |
| 1979 |
return true; |
1979 |
return true; |
| 1980 |
} |
1980 |
} |
| 1981 |
|
1981 |
|
| 1982 |
bool isConstPoolAsmImm() const { |
1982 |
bool isConstPoolAsmImm() const { |
| 1983 |
// Delay processing of Constant Pool Immediate, this will turn into |
1983 |
// Delay processing of Constant Pool Immediate, this will turn into |
| 1984 |
// a constant. Match no other operand |
1984 |
// a constant. Match no other operand |
| 1985 |
return (isConstantPoolImm()); |
1985 |
return (isConstantPoolImm()); |
| 1986 |
} |
1986 |
} |
| 1987 |
|
1987 |
|
| 1988 |
bool isPostIdxImm8() const { |
1988 |
bool isPostIdxImm8() const { |
| 1989 |
if (!isImm()) return false; |
1989 |
if (!isImm()) return false; |
| 1990 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1990 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 1991 |
if (!CE) return false; |
1991 |
if (!CE) return false; |
| 1992 |
int64_t Val = CE->getValue(); |
1992 |
int64_t Val = CE->getValue(); |
| 1993 |
return (Val > -256 && Val < 256) || |
1993 |
return (Val > -256 && Val < 256) || |
| 1994 |
(Val == std::numeric_limits::min()); |
1994 |
(Val == std::numeric_limits::min()); |
| 1995 |
} |
1995 |
} |
| 1996 |
|
1996 |
|
| 1997 |
bool isPostIdxImm8s4() const { |
1997 |
bool isPostIdxImm8s4() const { |
| 1998 |
if (!isImm()) return false; |
1998 |
if (!isImm()) return false; |
| 1999 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
1999 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2000 |
if (!CE) return false; |
2000 |
if (!CE) return false; |
| 2001 |
int64_t Val = CE->getValue(); |
2001 |
int64_t Val = CE->getValue(); |
| 2002 |
return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) || |
2002 |
return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) || |
| 2003 |
(Val == std::numeric_limits::min()); |
2003 |
(Val == std::numeric_limits::min()); |
| 2004 |
} |
2004 |
} |
| 2005 |
|
2005 |
|
| 2006 |
bool isMSRMask() const { return Kind == k_MSRMask; } |
2006 |
bool isMSRMask() const { return Kind == k_MSRMask; } |
| 2007 |
bool isBankedReg() const { return Kind == k_BankedReg; } |
2007 |
bool isBankedReg() const { return Kind == k_BankedReg; } |
| 2008 |
bool isProcIFlags() const { return Kind == k_ProcIFlags; } |
2008 |
bool isProcIFlags() const { return Kind == k_ProcIFlags; } |
| 2009 |
|
2009 |
|
| 2010 |
// NEON operands. |
2010 |
// NEON operands. |
| 2011 |
bool isSingleSpacedVectorList() const { |
2011 |
bool isSingleSpacedVectorList() const { |
| 2012 |
return Kind == k_VectorList && !VectorList.isDoubleSpaced; |
2012 |
return Kind == k_VectorList && !VectorList.isDoubleSpaced; |
| 2013 |
} |
2013 |
} |
| 2014 |
|
2014 |
|
| 2015 |
bool isDoubleSpacedVectorList() const { |
2015 |
bool isDoubleSpacedVectorList() const { |
| 2016 |
return Kind == k_VectorList && VectorList.isDoubleSpaced; |
2016 |
return Kind == k_VectorList && VectorList.isDoubleSpaced; |
| 2017 |
} |
2017 |
} |
| 2018 |
|
2018 |
|
| 2019 |
bool isVecListOneD() const { |
2019 |
bool isVecListOneD() const { |
| 2020 |
if (!isSingleSpacedVectorList()) return false; |
2020 |
if (!isSingleSpacedVectorList()) return false; |
| 2021 |
return VectorList.Count == 1; |
2021 |
return VectorList.Count == 1; |
| 2022 |
} |
2022 |
} |
| 2023 |
|
2023 |
|
| 2024 |
bool isVecListTwoMQ() const { |
2024 |
bool isVecListTwoMQ() const { |
| 2025 |
return isSingleSpacedVectorList() && VectorList.Count == 2 && |
2025 |
return isSingleSpacedVectorList() && VectorList.Count == 2 && |
| 2026 |
ARMMCRegisterClasses[ARM::MQPRRegClassID].contains( |
2026 |
ARMMCRegisterClasses[ARM::MQPRRegClassID].contains( |
| 2027 |
VectorList.RegNum); |
2027 |
VectorList.RegNum); |
| 2028 |
} |
2028 |
} |
| 2029 |
|
2029 |
|
| 2030 |
bool isVecListDPair() const { |
2030 |
bool isVecListDPair() const { |
| 2031 |
if (!isSingleSpacedVectorList()) return false; |
2031 |
if (!isSingleSpacedVectorList()) return false; |
| 2032 |
return (ARMMCRegisterClasses[ARM::DPairRegClassID] |
2032 |
return (ARMMCRegisterClasses[ARM::DPairRegClassID] |
| 2033 |
.contains(VectorList.RegNum)); |
2033 |
.contains(VectorList.RegNum)); |
| 2034 |
} |
2034 |
} |
| 2035 |
|
2035 |
|
| 2036 |
bool isVecListThreeD() const { |
2036 |
bool isVecListThreeD() const { |
| 2037 |
if (!isSingleSpacedVectorList()) return false; |
2037 |
if (!isSingleSpacedVectorList()) return false; |
| 2038 |
return VectorList.Count == 3; |
2038 |
return VectorList.Count == 3; |
| 2039 |
} |
2039 |
} |
| 2040 |
|
2040 |
|
| 2041 |
bool isVecListFourD() const { |
2041 |
bool isVecListFourD() const { |
| 2042 |
if (!isSingleSpacedVectorList()) return false; |
2042 |
if (!isSingleSpacedVectorList()) return false; |
| 2043 |
return VectorList.Count == 4; |
2043 |
return VectorList.Count == 4; |
| 2044 |
} |
2044 |
} |
| 2045 |
|
2045 |
|
| 2046 |
bool isVecListDPairSpaced() const { |
2046 |
bool isVecListDPairSpaced() const { |
| 2047 |
if (Kind != k_VectorList) return false; |
2047 |
if (Kind != k_VectorList) return false; |
| 2048 |
if (isSingleSpacedVectorList()) return false; |
2048 |
if (isSingleSpacedVectorList()) return false; |
| 2049 |
return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID] |
2049 |
return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID] |
| 2050 |
.contains(VectorList.RegNum)); |
2050 |
.contains(VectorList.RegNum)); |
| 2051 |
} |
2051 |
} |
| 2052 |
|
2052 |
|
| 2053 |
bool isVecListThreeQ() const { |
2053 |
bool isVecListThreeQ() const { |
| 2054 |
if (!isDoubleSpacedVectorList()) return false; |
2054 |
if (!isDoubleSpacedVectorList()) return false; |
| 2055 |
return VectorList.Count == 3; |
2055 |
return VectorList.Count == 3; |
| 2056 |
} |
2056 |
} |
| 2057 |
|
2057 |
|
| 2058 |
bool isVecListFourQ() const { |
2058 |
bool isVecListFourQ() const { |
| 2059 |
if (!isDoubleSpacedVectorList()) return false; |
2059 |
if (!isDoubleSpacedVectorList()) return false; |
| 2060 |
return VectorList.Count == 4; |
2060 |
return VectorList.Count == 4; |
| 2061 |
} |
2061 |
} |
| 2062 |
|
2062 |
|
| 2063 |
bool isVecListFourMQ() const { |
2063 |
bool isVecListFourMQ() const { |
| 2064 |
return isSingleSpacedVectorList() && VectorList.Count == 4 && |
2064 |
return isSingleSpacedVectorList() && VectorList.Count == 4 && |
| 2065 |
ARMMCRegisterClasses[ARM::MQPRRegClassID].contains( |
2065 |
ARMMCRegisterClasses[ARM::MQPRRegClassID].contains( |
| 2066 |
VectorList.RegNum); |
2066 |
VectorList.RegNum); |
| 2067 |
} |
2067 |
} |
| 2068 |
|
2068 |
|
| 2069 |
bool isSingleSpacedVectorAllLanes() const { |
2069 |
bool isSingleSpacedVectorAllLanes() const { |
| 2070 |
return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced; |
2070 |
return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced; |
| 2071 |
} |
2071 |
} |
| 2072 |
|
2072 |
|
| 2073 |
bool isDoubleSpacedVectorAllLanes() const { |
2073 |
bool isDoubleSpacedVectorAllLanes() const { |
| 2074 |
return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced; |
2074 |
return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced; |
| 2075 |
} |
2075 |
} |
| 2076 |
|
2076 |
|
| 2077 |
bool isVecListOneDAllLanes() const { |
2077 |
bool isVecListOneDAllLanes() const { |
| 2078 |
if (!isSingleSpacedVectorAllLanes()) return false; |
2078 |
if (!isSingleSpacedVectorAllLanes()) return false; |
| 2079 |
return VectorList.Count == 1; |
2079 |
return VectorList.Count == 1; |
| 2080 |
} |
2080 |
} |
| 2081 |
|
2081 |
|
| 2082 |
bool isVecListDPairAllLanes() const { |
2082 |
bool isVecListDPairAllLanes() const { |
| 2083 |
if (!isSingleSpacedVectorAllLanes()) return false; |
2083 |
if (!isSingleSpacedVectorAllLanes()) return false; |
| 2084 |
return (ARMMCRegisterClasses[ARM::DPairRegClassID] |
2084 |
return (ARMMCRegisterClasses[ARM::DPairRegClassID] |
| 2085 |
.contains(VectorList.RegNum)); |
2085 |
.contains(VectorList.RegNum)); |
| 2086 |
} |
2086 |
} |
| 2087 |
|
2087 |
|
| 2088 |
bool isVecListDPairSpacedAllLanes() const { |
2088 |
bool isVecListDPairSpacedAllLanes() const { |
| 2089 |
if (!isDoubleSpacedVectorAllLanes()) return false; |
2089 |
if (!isDoubleSpacedVectorAllLanes()) return false; |
| 2090 |
return VectorList.Count == 2; |
2090 |
return VectorList.Count == 2; |
| 2091 |
} |
2091 |
} |
| 2092 |
|
2092 |
|
| 2093 |
bool isVecListThreeDAllLanes() const { |
2093 |
bool isVecListThreeDAllLanes() const { |
| 2094 |
if (!isSingleSpacedVectorAllLanes()) return false; |
2094 |
if (!isSingleSpacedVectorAllLanes()) return false; |
| 2095 |
return VectorList.Count == 3; |
2095 |
return VectorList.Count == 3; |
| 2096 |
} |
2096 |
} |
| 2097 |
|
2097 |
|
| 2098 |
bool isVecListThreeQAllLanes() const { |
2098 |
bool isVecListThreeQAllLanes() const { |
| 2099 |
if (!isDoubleSpacedVectorAllLanes()) return false; |
2099 |
if (!isDoubleSpacedVectorAllLanes()) return false; |
| 2100 |
return VectorList.Count == 3; |
2100 |
return VectorList.Count == 3; |
| 2101 |
} |
2101 |
} |
| 2102 |
|
2102 |
|
| 2103 |
bool isVecListFourDAllLanes() const { |
2103 |
bool isVecListFourDAllLanes() const { |
| 2104 |
if (!isSingleSpacedVectorAllLanes()) return false; |
2104 |
if (!isSingleSpacedVectorAllLanes()) return false; |
| 2105 |
return VectorList.Count == 4; |
2105 |
return VectorList.Count == 4; |
| 2106 |
} |
2106 |
} |
| 2107 |
|
2107 |
|
| 2108 |
bool isVecListFourQAllLanes() const { |
2108 |
bool isVecListFourQAllLanes() const { |
| 2109 |
if (!isDoubleSpacedVectorAllLanes()) return false; |
2109 |
if (!isDoubleSpacedVectorAllLanes()) return false; |
| 2110 |
return VectorList.Count == 4; |
2110 |
return VectorList.Count == 4; |
| 2111 |
} |
2111 |
} |
| 2112 |
|
2112 |
|
| 2113 |
bool isSingleSpacedVectorIndexed() const { |
2113 |
bool isSingleSpacedVectorIndexed() const { |
| 2114 |
return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced; |
2114 |
return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced; |
| 2115 |
} |
2115 |
} |
| 2116 |
|
2116 |
|
| 2117 |
bool isDoubleSpacedVectorIndexed() const { |
2117 |
bool isDoubleSpacedVectorIndexed() const { |
| 2118 |
return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced; |
2118 |
return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced; |
| 2119 |
} |
2119 |
} |
| 2120 |
|
2120 |
|
| 2121 |
bool isVecListOneDByteIndexed() const { |
2121 |
bool isVecListOneDByteIndexed() const { |
| 2122 |
if (!isSingleSpacedVectorIndexed()) return false; |
2122 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2123 |
return VectorList.Count == 1 && VectorList.LaneIndex <= 7; |
2123 |
return VectorList.Count == 1 && VectorList.LaneIndex <= 7; |
| 2124 |
} |
2124 |
} |
| 2125 |
|
2125 |
|
| 2126 |
bool isVecListOneDHWordIndexed() const { |
2126 |
bool isVecListOneDHWordIndexed() const { |
| 2127 |
if (!isSingleSpacedVectorIndexed()) return false; |
2127 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2128 |
return VectorList.Count == 1 && VectorList.LaneIndex <= 3; |
2128 |
return VectorList.Count == 1 && VectorList.LaneIndex <= 3; |
| 2129 |
} |
2129 |
} |
| 2130 |
|
2130 |
|
| 2131 |
bool isVecListOneDWordIndexed() const { |
2131 |
bool isVecListOneDWordIndexed() const { |
| 2132 |
if (!isSingleSpacedVectorIndexed()) return false; |
2132 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2133 |
return VectorList.Count == 1 && VectorList.LaneIndex <= 1; |
2133 |
return VectorList.Count == 1 && VectorList.LaneIndex <= 1; |
| 2134 |
} |
2134 |
} |
| 2135 |
|
2135 |
|
| 2136 |
bool isVecListTwoDByteIndexed() const { |
2136 |
bool isVecListTwoDByteIndexed() const { |
| 2137 |
if (!isSingleSpacedVectorIndexed()) return false; |
2137 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2138 |
return VectorList.Count == 2 && VectorList.LaneIndex <= 7; |
2138 |
return VectorList.Count == 2 && VectorList.LaneIndex <= 7; |
| 2139 |
} |
2139 |
} |
| 2140 |
|
2140 |
|
| 2141 |
bool isVecListTwoDHWordIndexed() const { |
2141 |
bool isVecListTwoDHWordIndexed() const { |
| 2142 |
if (!isSingleSpacedVectorIndexed()) return false; |
2142 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2143 |
return VectorList.Count == 2 && VectorList.LaneIndex <= 3; |
2143 |
return VectorList.Count == 2 && VectorList.LaneIndex <= 3; |
| 2144 |
} |
2144 |
} |
| 2145 |
|
2145 |
|
| 2146 |
bool isVecListTwoQWordIndexed() const { |
2146 |
bool isVecListTwoQWordIndexed() const { |
| 2147 |
if (!isDoubleSpacedVectorIndexed()) return false; |
2147 |
if (!isDoubleSpacedVectorIndexed()) return false; |
| 2148 |
return VectorList.Count == 2 && VectorList.LaneIndex <= 1; |
2148 |
return VectorList.Count == 2 && VectorList.LaneIndex <= 1; |
| 2149 |
} |
2149 |
} |
| 2150 |
|
2150 |
|
| 2151 |
bool isVecListTwoQHWordIndexed() const { |
2151 |
bool isVecListTwoQHWordIndexed() const { |
| 2152 |
if (!isDoubleSpacedVectorIndexed()) return false; |
2152 |
if (!isDoubleSpacedVectorIndexed()) return false; |
| 2153 |
return VectorList.Count == 2 && VectorList.LaneIndex <= 3; |
2153 |
return VectorList.Count == 2 && VectorList.LaneIndex <= 3; |
| 2154 |
} |
2154 |
} |
| 2155 |
|
2155 |
|
| 2156 |
bool isVecListTwoDWordIndexed() const { |
2156 |
bool isVecListTwoDWordIndexed() const { |
| 2157 |
if (!isSingleSpacedVectorIndexed()) return false; |
2157 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2158 |
return VectorList.Count == 2 && VectorList.LaneIndex <= 1; |
2158 |
return VectorList.Count == 2 && VectorList.LaneIndex <= 1; |
| 2159 |
} |
2159 |
} |
| 2160 |
|
2160 |
|
| 2161 |
bool isVecListThreeDByteIndexed() const { |
2161 |
bool isVecListThreeDByteIndexed() const { |
| 2162 |
if (!isSingleSpacedVectorIndexed()) return false; |
2162 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2163 |
return VectorList.Count == 3 && VectorList.LaneIndex <= 7; |
2163 |
return VectorList.Count == 3 && VectorList.LaneIndex <= 7; |
| 2164 |
} |
2164 |
} |
| 2165 |
|
2165 |
|
| 2166 |
bool isVecListThreeDHWordIndexed() const { |
2166 |
bool isVecListThreeDHWordIndexed() const { |
| 2167 |
if (!isSingleSpacedVectorIndexed()) return false; |
2167 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2168 |
return VectorList.Count == 3 && VectorList.LaneIndex <= 3; |
2168 |
return VectorList.Count == 3 && VectorList.LaneIndex <= 3; |
| 2169 |
} |
2169 |
} |
| 2170 |
|
2170 |
|
| 2171 |
bool isVecListThreeQWordIndexed() const { |
2171 |
bool isVecListThreeQWordIndexed() const { |
| 2172 |
if (!isDoubleSpacedVectorIndexed()) return false; |
2172 |
if (!isDoubleSpacedVectorIndexed()) return false; |
| 2173 |
return VectorList.Count == 3 && VectorList.LaneIndex <= 1; |
2173 |
return VectorList.Count == 3 && VectorList.LaneIndex <= 1; |
| 2174 |
} |
2174 |
} |
| 2175 |
|
2175 |
|
| 2176 |
bool isVecListThreeQHWordIndexed() const { |
2176 |
bool isVecListThreeQHWordIndexed() const { |
| 2177 |
if (!isDoubleSpacedVectorIndexed()) return false; |
2177 |
if (!isDoubleSpacedVectorIndexed()) return false; |
| 2178 |
return VectorList.Count == 3 && VectorList.LaneIndex <= 3; |
2178 |
return VectorList.Count == 3 && VectorList.LaneIndex <= 3; |
| 2179 |
} |
2179 |
} |
| 2180 |
|
2180 |
|
| 2181 |
bool isVecListThreeDWordIndexed() const { |
2181 |
bool isVecListThreeDWordIndexed() const { |
| 2182 |
if (!isSingleSpacedVectorIndexed()) return false; |
2182 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2183 |
return VectorList.Count == 3 && VectorList.LaneIndex <= 1; |
2183 |
return VectorList.Count == 3 && VectorList.LaneIndex <= 1; |
| 2184 |
} |
2184 |
} |
| 2185 |
|
2185 |
|
| 2186 |
bool isVecListFourDByteIndexed() const { |
2186 |
bool isVecListFourDByteIndexed() const { |
| 2187 |
if (!isSingleSpacedVectorIndexed()) return false; |
2187 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2188 |
return VectorList.Count == 4 && VectorList.LaneIndex <= 7; |
2188 |
return VectorList.Count == 4 && VectorList.LaneIndex <= 7; |
| 2189 |
} |
2189 |
} |
| 2190 |
|
2190 |
|
| 2191 |
bool isVecListFourDHWordIndexed() const { |
2191 |
bool isVecListFourDHWordIndexed() const { |
| 2192 |
if (!isSingleSpacedVectorIndexed()) return false; |
2192 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2193 |
return VectorList.Count == 4 && VectorList.LaneIndex <= 3; |
2193 |
return VectorList.Count == 4 && VectorList.LaneIndex <= 3; |
| 2194 |
} |
2194 |
} |
| 2195 |
|
2195 |
|
| 2196 |
bool isVecListFourQWordIndexed() const { |
2196 |
bool isVecListFourQWordIndexed() const { |
| 2197 |
if (!isDoubleSpacedVectorIndexed()) return false; |
2197 |
if (!isDoubleSpacedVectorIndexed()) return false; |
| 2198 |
return VectorList.Count == 4 && VectorList.LaneIndex <= 1; |
2198 |
return VectorList.Count == 4 && VectorList.LaneIndex <= 1; |
| 2199 |
} |
2199 |
} |
| 2200 |
|
2200 |
|
| 2201 |
bool isVecListFourQHWordIndexed() const { |
2201 |
bool isVecListFourQHWordIndexed() const { |
| 2202 |
if (!isDoubleSpacedVectorIndexed()) return false; |
2202 |
if (!isDoubleSpacedVectorIndexed()) return false; |
| 2203 |
return VectorList.Count == 4 && VectorList.LaneIndex <= 3; |
2203 |
return VectorList.Count == 4 && VectorList.LaneIndex <= 3; |
| 2204 |
} |
2204 |
} |
| 2205 |
|
2205 |
|
| 2206 |
bool isVecListFourDWordIndexed() const { |
2206 |
bool isVecListFourDWordIndexed() const { |
| 2207 |
if (!isSingleSpacedVectorIndexed()) return false; |
2207 |
if (!isSingleSpacedVectorIndexed()) return false; |
| 2208 |
return VectorList.Count == 4 && VectorList.LaneIndex <= 1; |
2208 |
return VectorList.Count == 4 && VectorList.LaneIndex <= 1; |
| 2209 |
} |
2209 |
} |
| 2210 |
|
2210 |
|
| 2211 |
bool isVectorIndex() const { return Kind == k_VectorIndex; } |
2211 |
bool isVectorIndex() const { return Kind == k_VectorIndex; } |
| 2212 |
|
2212 |
|
| 2213 |
template |
2213 |
template |
| 2214 |
bool isVectorIndexInRange() const { |
2214 |
bool isVectorIndexInRange() const { |
| 2215 |
if (Kind != k_VectorIndex) return false; |
2215 |
if (Kind != k_VectorIndex) return false; |
| 2216 |
return VectorIndex.Val < NumLanes; |
2216 |
return VectorIndex.Val < NumLanes; |
| 2217 |
} |
2217 |
} |
| 2218 |
|
2218 |
|
| 2219 |
bool isVectorIndex8() const { return isVectorIndexInRange<8>(); } |
2219 |
bool isVectorIndex8() const { return isVectorIndexInRange<8>(); } |
| 2220 |
bool isVectorIndex16() const { return isVectorIndexInRange<4>(); } |
2220 |
bool isVectorIndex16() const { return isVectorIndexInRange<4>(); } |
| 2221 |
bool isVectorIndex32() const { return isVectorIndexInRange<2>(); } |
2221 |
bool isVectorIndex32() const { return isVectorIndexInRange<2>(); } |
| 2222 |
bool isVectorIndex64() const { return isVectorIndexInRange<1>(); } |
2222 |
bool isVectorIndex64() const { return isVectorIndexInRange<1>(); } |
| 2223 |
|
2223 |
|
| 2224 |
template |
2224 |
template |
| 2225 |
bool isMVEPairVectorIndex() const { |
2225 |
bool isMVEPairVectorIndex() const { |
| 2226 |
if (Kind != k_VectorIndex) return false; |
2226 |
if (Kind != k_VectorIndex) return false; |
| 2227 |
return VectorIndex.Val == PermittedValue || |
2227 |
return VectorIndex.Val == PermittedValue || |
| 2228 |
VectorIndex.Val == OtherPermittedValue; |
2228 |
VectorIndex.Val == OtherPermittedValue; |
| 2229 |
} |
2229 |
} |
| 2230 |
|
2230 |
|
| 2231 |
bool isNEONi8splat() const { |
2231 |
bool isNEONi8splat() const { |
| 2232 |
if (!isImm()) return false; |
2232 |
if (!isImm()) return false; |
| 2233 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2233 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2234 |
// Must be a constant. |
2234 |
// Must be a constant. |
| 2235 |
if (!CE) return false; |
2235 |
if (!CE) return false; |
| 2236 |
int64_t Value = CE->getValue(); |
2236 |
int64_t Value = CE->getValue(); |
| 2237 |
// i8 value splatted across 8 bytes. The immediate is just the 8 byte |
2237 |
// i8 value splatted across 8 bytes. The immediate is just the 8 byte |
| 2238 |
// value. |
2238 |
// value. |
| 2239 |
return Value >= 0 && Value < 256; |
2239 |
return Value >= 0 && Value < 256; |
| 2240 |
} |
2240 |
} |
| 2241 |
|
2241 |
|
| 2242 |
bool isNEONi16splat() const { |
2242 |
bool isNEONi16splat() const { |
| 2243 |
if (isNEONByteReplicate(2)) |
2243 |
if (isNEONByteReplicate(2)) |
| 2244 |
return false; // Leave that for bytes replication and forbid by default. |
2244 |
return false; // Leave that for bytes replication and forbid by default. |
| 2245 |
if (!isImm()) |
2245 |
if (!isImm()) |
| 2246 |
return false; |
2246 |
return false; |
| 2247 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2247 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2248 |
// Must be a constant. |
2248 |
// Must be a constant. |
| 2249 |
if (!CE) return false; |
2249 |
if (!CE) return false; |
| 2250 |
unsigned Value = CE->getValue(); |
2250 |
unsigned Value = CE->getValue(); |
| 2251 |
return ARM_AM::isNEONi16splat(Value); |
2251 |
return ARM_AM::isNEONi16splat(Value); |
| 2252 |
} |
2252 |
} |
| 2253 |
|
2253 |
|
| 2254 |
bool isNEONi16splatNot() const { |
2254 |
bool isNEONi16splatNot() const { |
| 2255 |
if (!isImm()) |
2255 |
if (!isImm()) |
| 2256 |
return false; |
2256 |
return false; |
| 2257 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2257 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2258 |
// Must be a constant. |
2258 |
// Must be a constant. |
| 2259 |
if (!CE) return false; |
2259 |
if (!CE) return false; |
| 2260 |
unsigned Value = CE->getValue(); |
2260 |
unsigned Value = CE->getValue(); |
| 2261 |
return ARM_AM::isNEONi16splat(~Value & 0xffff); |
2261 |
return ARM_AM::isNEONi16splat(~Value & 0xffff); |
| 2262 |
} |
2262 |
} |
| 2263 |
|
2263 |
|
| 2264 |
bool isNEONi32splat() const { |
2264 |
bool isNEONi32splat() const { |
| 2265 |
if (isNEONByteReplicate(4)) |
2265 |
if (isNEONByteReplicate(4)) |
| 2266 |
return false; // Leave that for bytes replication and forbid by default. |
2266 |
return false; // Leave that for bytes replication and forbid by default. |
| 2267 |
if (!isImm()) |
2267 |
if (!isImm()) |
| 2268 |
return false; |
2268 |
return false; |
| 2269 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2269 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2270 |
// Must be a constant. |
2270 |
// Must be a constant. |
| 2271 |
if (!CE) return false; |
2271 |
if (!CE) return false; |
| 2272 |
unsigned Value = CE->getValue(); |
2272 |
unsigned Value = CE->getValue(); |
| 2273 |
return ARM_AM::isNEONi32splat(Value); |
2273 |
return ARM_AM::isNEONi32splat(Value); |
| 2274 |
} |
2274 |
} |
| 2275 |
|
2275 |
|
| 2276 |
bool isNEONi32splatNot() const { |
2276 |
bool isNEONi32splatNot() const { |
| 2277 |
if (!isImm()) |
2277 |
if (!isImm()) |
| 2278 |
return false; |
2278 |
return false; |
| 2279 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2279 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2280 |
// Must be a constant. |
2280 |
// Must be a constant. |
| 2281 |
if (!CE) return false; |
2281 |
if (!CE) return false; |
| 2282 |
unsigned Value = CE->getValue(); |
2282 |
unsigned Value = CE->getValue(); |
| 2283 |
return ARM_AM::isNEONi32splat(~Value); |
2283 |
return ARM_AM::isNEONi32splat(~Value); |
| 2284 |
} |
2284 |
} |
| 2285 |
|
2285 |
|
| 2286 |
static bool isValidNEONi32vmovImm(int64_t Value) { |
2286 |
static bool isValidNEONi32vmovImm(int64_t Value) { |
| 2287 |
// i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X, |
2287 |
// i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X, |
| 2288 |
// for VMOV/VMVN only, 00Xf or 0Xff are also accepted. |
2288 |
// for VMOV/VMVN only, 00Xf or 0Xff are also accepted. |
| 2289 |
return ((Value & 0xffffffffffffff00) == 0) || |
2289 |
return ((Value & 0xffffffffffffff00) == 0) || |
| 2290 |
((Value & 0xffffffffffff00ff) == 0) || |
2290 |
((Value & 0xffffffffffff00ff) == 0) || |
| 2291 |
((Value & 0xffffffffff00ffff) == 0) || |
2291 |
((Value & 0xffffffffff00ffff) == 0) || |
| 2292 |
((Value & 0xffffffff00ffffff) == 0) || |
2292 |
((Value & 0xffffffff00ffffff) == 0) || |
| 2293 |
((Value & 0xffffffffffff00ff) == 0xff) || |
2293 |
((Value & 0xffffffffffff00ff) == 0xff) || |
| 2294 |
((Value & 0xffffffffff00ffff) == 0xffff); |
2294 |
((Value & 0xffffffffff00ffff) == 0xffff); |
| 2295 |
} |
2295 |
} |
| 2296 |
|
2296 |
|
| 2297 |
bool isNEONReplicate(unsigned Width, unsigned NumElems, bool Inv) const { |
2297 |
bool isNEONReplicate(unsigned Width, unsigned NumElems, bool Inv) const { |
| 2298 |
assert((Width == 8 || Width == 16 || Width == 32) && |
2298 |
assert((Width == 8 || Width == 16 || Width == 32) && |
| 2299 |
"Invalid element width"); |
2299 |
"Invalid element width"); |
| 2300 |
assert(NumElems * Width <= 64 && "Invalid result width"); |
2300 |
assert(NumElems * Width <= 64 && "Invalid result width"); |
| 2301 |
|
2301 |
|
| 2302 |
if (!isImm()) |
2302 |
if (!isImm()) |
| 2303 |
return false; |
2303 |
return false; |
| 2304 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2304 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2305 |
// Must be a constant. |
2305 |
// Must be a constant. |
| 2306 |
if (!CE) |
2306 |
if (!CE) |
| 2307 |
return false; |
2307 |
return false; |
| 2308 |
int64_t Value = CE->getValue(); |
2308 |
int64_t Value = CE->getValue(); |
| 2309 |
if (!Value) |
2309 |
if (!Value) |
| 2310 |
return false; // Don't bother with zero. |
2310 |
return false; // Don't bother with zero. |
| 2311 |
if (Inv) |
2311 |
if (Inv) |
| 2312 |
Value = ~Value; |
2312 |
Value = ~Value; |
| 2313 |
|
2313 |
|
| 2314 |
uint64_t Mask = (1ull << Width) - 1; |
2314 |
uint64_t Mask = (1ull << Width) - 1; |
| 2315 |
uint64_t Elem = Value & Mask; |
2315 |
uint64_t Elem = Value & Mask; |
| 2316 |
if (Width == 16 && (Elem & 0x00ff) != 0 && (Elem & 0xff00) != 0) |
2316 |
if (Width == 16 && (Elem & 0x00ff) != 0 && (Elem & 0xff00) != 0) |
| 2317 |
return false; |
2317 |
return false; |
| 2318 |
if (Width == 32 && !isValidNEONi32vmovImm(Elem)) |
2318 |
if (Width == 32 && !isValidNEONi32vmovImm(Elem)) |
| 2319 |
return false; |
2319 |
return false; |
| 2320 |
|
2320 |
|
| 2321 |
for (unsigned i = 1; i < NumElems; ++i) { |
2321 |
for (unsigned i = 1; i < NumElems; ++i) { |
| 2322 |
Value >>= Width; |
2322 |
Value >>= Width; |
| 2323 |
if ((Value & Mask) != Elem) |
2323 |
if ((Value & Mask) != Elem) |
| 2324 |
return false; |
2324 |
return false; |
| 2325 |
} |
2325 |
} |
| 2326 |
return true; |
2326 |
return true; |
| 2327 |
} |
2327 |
} |
| 2328 |
|
2328 |
|
| 2329 |
bool isNEONByteReplicate(unsigned NumBytes) const { |
2329 |
bool isNEONByteReplicate(unsigned NumBytes) const { |
| 2330 |
return isNEONReplicate(8, NumBytes, false); |
2330 |
return isNEONReplicate(8, NumBytes, false); |
| 2331 |
} |
2331 |
} |
| 2332 |
|
2332 |
|
| 2333 |
static void checkNeonReplicateArgs(unsigned FromW, unsigned ToW) { |
2333 |
static void checkNeonReplicateArgs(unsigned FromW, unsigned ToW) { |
| 2334 |
assert((FromW == 8 || FromW == 16 || FromW == 32) && |
2334 |
assert((FromW == 8 || FromW == 16 || FromW == 32) && |
| 2335 |
"Invalid source width"); |
2335 |
"Invalid source width"); |
| 2336 |
assert((ToW == 16 || ToW == 32 || ToW == 64) && |
2336 |
assert((ToW == 16 || ToW == 32 || ToW == 64) && |
| 2337 |
"Invalid destination width"); |
2337 |
"Invalid destination width"); |
| 2338 |
assert(FromW < ToW && "ToW is not less than FromW"); |
2338 |
assert(FromW < ToW && "ToW is not less than FromW"); |
| 2339 |
} |
2339 |
} |
| 2340 |
|
2340 |
|
| 2341 |
template |
2341 |
template |
| 2342 |
bool isNEONmovReplicate() const { |
2342 |
bool isNEONmovReplicate() const { |
| 2343 |
checkNeonReplicateArgs(FromW, ToW); |
2343 |
checkNeonReplicateArgs(FromW, ToW); |
| 2344 |
if (ToW == 64 && isNEONi64splat()) |
2344 |
if (ToW == 64 && isNEONi64splat()) |
| 2345 |
return false; |
2345 |
return false; |
| 2346 |
return isNEONReplicate(FromW, ToW / FromW, false); |
2346 |
return isNEONReplicate(FromW, ToW / FromW, false); |
| 2347 |
} |
2347 |
} |
| 2348 |
|
2348 |
|
| 2349 |
template |
2349 |
template |
| 2350 |
bool isNEONinvReplicate() const { |
2350 |
bool isNEONinvReplicate() const { |
| 2351 |
checkNeonReplicateArgs(FromW, ToW); |
2351 |
checkNeonReplicateArgs(FromW, ToW); |
| 2352 |
return isNEONReplicate(FromW, ToW / FromW, true); |
2352 |
return isNEONReplicate(FromW, ToW / FromW, true); |
| 2353 |
} |
2353 |
} |
| 2354 |
|
2354 |
|
| 2355 |
bool isNEONi32vmov() const { |
2355 |
bool isNEONi32vmov() const { |
| 2356 |
if (isNEONByteReplicate(4)) |
2356 |
if (isNEONByteReplicate(4)) |
| 2357 |
return false; // Let it to be classified as byte-replicate case. |
2357 |
return false; // Let it to be classified as byte-replicate case. |
| 2358 |
if (!isImm()) |
2358 |
if (!isImm()) |
| 2359 |
return false; |
2359 |
return false; |
| 2360 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2360 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2361 |
// Must be a constant. |
2361 |
// Must be a constant. |
| 2362 |
if (!CE) |
2362 |
if (!CE) |
| 2363 |
return false; |
2363 |
return false; |
| 2364 |
return isValidNEONi32vmovImm(CE->getValue()); |
2364 |
return isValidNEONi32vmovImm(CE->getValue()); |
| 2365 |
} |
2365 |
} |
| 2366 |
|
2366 |
|
| 2367 |
bool isNEONi32vmovNeg() const { |
2367 |
bool isNEONi32vmovNeg() const { |
| 2368 |
if (!isImm()) return false; |
2368 |
if (!isImm()) return false; |
| 2369 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2369 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2370 |
// Must be a constant. |
2370 |
// Must be a constant. |
| 2371 |
if (!CE) return false; |
2371 |
if (!CE) return false; |
| 2372 |
return isValidNEONi32vmovImm(~CE->getValue()); |
2372 |
return isValidNEONi32vmovImm(~CE->getValue()); |
| 2373 |
} |
2373 |
} |
| 2374 |
|
2374 |
|
| 2375 |
bool isNEONi64splat() const { |
2375 |
bool isNEONi64splat() const { |
| 2376 |
if (!isImm()) return false; |
2376 |
if (!isImm()) return false; |
| 2377 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2377 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2378 |
// Must be a constant. |
2378 |
// Must be a constant. |
| 2379 |
if (!CE) return false; |
2379 |
if (!CE) return false; |
| 2380 |
uint64_t Value = CE->getValue(); |
2380 |
uint64_t Value = CE->getValue(); |
| 2381 |
// i64 value with each byte being either 0 or 0xff. |
2381 |
// i64 value with each byte being either 0 or 0xff. |
| 2382 |
for (unsigned i = 0; i < 8; ++i, Value >>= 8) |
2382 |
for (unsigned i = 0; i < 8; ++i, Value >>= 8) |
| 2383 |
if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false; |
2383 |
if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false; |
| 2384 |
return true; |
2384 |
return true; |
| 2385 |
} |
2385 |
} |
| 2386 |
|
2386 |
|
| 2387 |
template |
2387 |
template |
| 2388 |
bool isComplexRotation() const { |
2388 |
bool isComplexRotation() const { |
| 2389 |
if (!isImm()) return false; |
2389 |
if (!isImm()) return false; |
| 2390 |
|
2390 |
|
| 2391 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2391 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2392 |
if (!CE) return false; |
2392 |
if (!CE) return false; |
| 2393 |
uint64_t Value = CE->getValue(); |
2393 |
uint64_t Value = CE->getValue(); |
| 2394 |
|
2394 |
|
| 2395 |
return (Value % Angle == Remainder && Value <= 270); |
2395 |
return (Value % Angle == Remainder && Value <= 270); |
| 2396 |
} |
2396 |
} |
| 2397 |
|
2397 |
|
| 2398 |
bool isMVELongShift() const { |
2398 |
bool isMVELongShift() const { |
| 2399 |
if (!isImm()) return false; |
2399 |
if (!isImm()) return false; |
| 2400 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2400 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2401 |
// Must be a constant. |
2401 |
// Must be a constant. |
| 2402 |
if (!CE) return false; |
2402 |
if (!CE) return false; |
| 2403 |
uint64_t Value = CE->getValue(); |
2403 |
uint64_t Value = CE->getValue(); |
| 2404 |
return Value >= 1 && Value <= 32; |
2404 |
return Value >= 1 && Value <= 32; |
| 2405 |
} |
2405 |
} |
| 2406 |
|
2406 |
|
| 2407 |
bool isMveSaturateOp() const { |
2407 |
bool isMveSaturateOp() const { |
| 2408 |
if (!isImm()) return false; |
2408 |
if (!isImm()) return false; |
| 2409 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2409 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2410 |
if (!CE) return false; |
2410 |
if (!CE) return false; |
| 2411 |
uint64_t Value = CE->getValue(); |
2411 |
uint64_t Value = CE->getValue(); |
| 2412 |
return Value == 48 || Value == 64; |
2412 |
return Value == 48 || Value == 64; |
| 2413 |
} |
2413 |
} |
| 2414 |
|
2414 |
|
| 2415 |
bool isITCondCodeNoAL() const { |
2415 |
bool isITCondCodeNoAL() const { |
| 2416 |
if (!isITCondCode()) return false; |
2416 |
if (!isITCondCode()) return false; |
| 2417 |
ARMCC::CondCodes CC = getCondCode(); |
2417 |
ARMCC::CondCodes CC = getCondCode(); |
| 2418 |
return CC != ARMCC::AL; |
2418 |
return CC != ARMCC::AL; |
| 2419 |
} |
2419 |
} |
| 2420 |
|
2420 |
|
| 2421 |
bool isITCondCodeRestrictedI() const { |
2421 |
bool isITCondCodeRestrictedI() const { |
| 2422 |
if (!isITCondCode()) |
2422 |
if (!isITCondCode()) |
| 2423 |
return false; |
2423 |
return false; |
| 2424 |
ARMCC::CondCodes CC = getCondCode(); |
2424 |
ARMCC::CondCodes CC = getCondCode(); |
| 2425 |
return CC == ARMCC::EQ || CC == ARMCC::NE; |
2425 |
return CC == ARMCC::EQ || CC == ARMCC::NE; |
| 2426 |
} |
2426 |
} |
| 2427 |
|
2427 |
|
| 2428 |
bool isITCondCodeRestrictedS() const { |
2428 |
bool isITCondCodeRestrictedS() const { |
| 2429 |
if (!isITCondCode()) |
2429 |
if (!isITCondCode()) |
| 2430 |
return false; |
2430 |
return false; |
| 2431 |
ARMCC::CondCodes CC = getCondCode(); |
2431 |
ARMCC::CondCodes CC = getCondCode(); |
| 2432 |
return CC == ARMCC::LT || CC == ARMCC::GT || CC == ARMCC::LE || |
2432 |
return CC == ARMCC::LT || CC == ARMCC::GT || CC == ARMCC::LE || |
| 2433 |
CC == ARMCC::GE; |
2433 |
CC == ARMCC::GE; |
| 2434 |
} |
2434 |
} |
| 2435 |
|
2435 |
|
| 2436 |
bool isITCondCodeRestrictedU() const { |
2436 |
bool isITCondCodeRestrictedU() const { |
| 2437 |
if (!isITCondCode()) |
2437 |
if (!isITCondCode()) |
| 2438 |
return false; |
2438 |
return false; |
| 2439 |
ARMCC::CondCodes CC = getCondCode(); |
2439 |
ARMCC::CondCodes CC = getCondCode(); |
| 2440 |
return CC == ARMCC::HS || CC == ARMCC::HI; |
2440 |
return CC == ARMCC::HS || CC == ARMCC::HI; |
| 2441 |
} |
2441 |
} |
| 2442 |
|
2442 |
|
| 2443 |
bool isITCondCodeRestrictedFP() const { |
2443 |
bool isITCondCodeRestrictedFP() const { |
| 2444 |
if (!isITCondCode()) |
2444 |
if (!isITCondCode()) |
| 2445 |
return false; |
2445 |
return false; |
| 2446 |
ARMCC::CondCodes CC = getCondCode(); |
2446 |
ARMCC::CondCodes CC = getCondCode(); |
| 2447 |
return CC == ARMCC::EQ || CC == ARMCC::NE || CC == ARMCC::LT || |
2447 |
return CC == ARMCC::EQ || CC == ARMCC::NE || CC == ARMCC::LT || |
| 2448 |
CC == ARMCC::GT || CC == ARMCC::LE || CC == ARMCC::GE; |
2448 |
CC == ARMCC::GT || CC == ARMCC::LE || CC == ARMCC::GE; |
| 2449 |
} |
2449 |
} |
| 2450 |
|
2450 |
|
| 2451 |
void addExpr(MCInst &Inst, const MCExpr *Expr) const { |
2451 |
void addExpr(MCInst &Inst, const MCExpr *Expr) const { |
| 2452 |
// Add as immediates when possible. Null MCExpr = 0. |
2452 |
// Add as immediates when possible. Null MCExpr = 0. |
| 2453 |
if (!Expr) |
2453 |
if (!Expr) |
| 2454 |
Inst.addOperand(MCOperand::createImm(0)); |
2454 |
Inst.addOperand(MCOperand::createImm(0)); |
| 2455 |
else if (const MCConstantExpr *CE = dyn_cast(Expr)) |
2455 |
else if (const MCConstantExpr *CE = dyn_cast(Expr)) |
| 2456 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
2456 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 2457 |
else |
2457 |
else |
| 2458 |
Inst.addOperand(MCOperand::createExpr(Expr)); |
2458 |
Inst.addOperand(MCOperand::createExpr(Expr)); |
| 2459 |
} |
2459 |
} |
| 2460 |
|
2460 |
|
| 2461 |
void addARMBranchTargetOperands(MCInst &Inst, unsigned N) const { |
2461 |
void addARMBranchTargetOperands(MCInst &Inst, unsigned N) const { |
| 2462 |
assert(N == 1 && "Invalid number of operands!"); |
2462 |
assert(N == 1 && "Invalid number of operands!"); |
| 2463 |
addExpr(Inst, getImm()); |
2463 |
addExpr(Inst, getImm()); |
| 2464 |
} |
2464 |
} |
| 2465 |
|
2465 |
|
| 2466 |
void addThumbBranchTargetOperands(MCInst &Inst, unsigned N) const { |
2466 |
void addThumbBranchTargetOperands(MCInst &Inst, unsigned N) const { |
| 2467 |
assert(N == 1 && "Invalid number of operands!"); |
2467 |
assert(N == 1 && "Invalid number of operands!"); |
| 2468 |
addExpr(Inst, getImm()); |
2468 |
addExpr(Inst, getImm()); |
| 2469 |
} |
2469 |
} |
| 2470 |
|
2470 |
|
| 2471 |
void addCondCodeOperands(MCInst &Inst, unsigned N) const { |
2471 |
void addCondCodeOperands(MCInst &Inst, unsigned N) const { |
| 2472 |
assert(N == 2 && "Invalid number of operands!"); |
2472 |
assert(N == 2 && "Invalid number of operands!"); |
| 2473 |
Inst.addOperand(MCOperand::createImm(unsigned(getCondCode()))); |
2473 |
Inst.addOperand(MCOperand::createImm(unsigned(getCondCode()))); |
| 2474 |
unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR; |
2474 |
unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR; |
| 2475 |
Inst.addOperand(MCOperand::createReg(RegNum)); |
2475 |
Inst.addOperand(MCOperand::createReg(RegNum)); |
| 2476 |
} |
2476 |
} |
| 2477 |
|
2477 |
|
| 2478 |
void addVPTPredNOperands(MCInst &Inst, unsigned N) const { |
2478 |
void addVPTPredNOperands(MCInst &Inst, unsigned N) const { |
| 2479 |
assert(N == 3 && "Invalid number of operands!"); |
2479 |
assert(N == 3 && "Invalid number of operands!"); |
| 2480 |
Inst.addOperand(MCOperand::createImm(unsigned(getVPTPred()))); |
2480 |
Inst.addOperand(MCOperand::createImm(unsigned(getVPTPred()))); |
| 2481 |
unsigned RegNum = getVPTPred() == ARMVCC::None ? 0: ARM::P0; |
2481 |
unsigned RegNum = getVPTPred() == ARMVCC::None ? 0: ARM::P0; |
| 2482 |
Inst.addOperand(MCOperand::createReg(RegNum)); |
2482 |
Inst.addOperand(MCOperand::createReg(RegNum)); |
| 2483 |
Inst.addOperand(MCOperand::createReg(0)); |
2483 |
Inst.addOperand(MCOperand::createReg(0)); |
| 2484 |
} |
2484 |
} |
| 2485 |
|
2485 |
|
| 2486 |
void addVPTPredROperands(MCInst &Inst, unsigned N) const { |
2486 |
void addVPTPredROperands(MCInst &Inst, unsigned N) const { |
| 2487 |
assert(N == 4 && "Invalid number of operands!"); |
2487 |
assert(N == 4 && "Invalid number of operands!"); |
| 2488 |
addVPTPredNOperands(Inst, N-1); |
2488 |
addVPTPredNOperands(Inst, N-1); |
| 2489 |
unsigned RegNum; |
2489 |
unsigned RegNum; |
| 2490 |
if (getVPTPred() == ARMVCC::None) { |
2490 |
if (getVPTPred() == ARMVCC::None) { |
| 2491 |
RegNum = 0; |
2491 |
RegNum = 0; |
| 2492 |
} else { |
2492 |
} else { |
| 2493 |
unsigned NextOpIndex = Inst.getNumOperands(); |
2493 |
unsigned NextOpIndex = Inst.getNumOperands(); |
| 2494 |
const MCInstrDesc &MCID = |
2494 |
const MCInstrDesc &MCID = |
| 2495 |
ARMDescs.Insts[ARM::INSTRUCTION_LIST_END - 1 - Inst.getOpcode()]; |
2495 |
ARMDescs.Insts[ARM::INSTRUCTION_LIST_END - 1 - Inst.getOpcode()]; |
| 2496 |
int TiedOp = MCID.getOperandConstraint(NextOpIndex, MCOI::TIED_TO); |
2496 |
int TiedOp = MCID.getOperandConstraint(NextOpIndex, MCOI::TIED_TO); |
| 2497 |
assert(TiedOp >= 0 && |
2497 |
assert(TiedOp >= 0 && |
| 2498 |
"Inactive register in vpred_r is not tied to an output!"); |
2498 |
"Inactive register in vpred_r is not tied to an output!"); |
| 2499 |
RegNum = Inst.getOperand(TiedOp).getReg(); |
2499 |
RegNum = Inst.getOperand(TiedOp).getReg(); |
| 2500 |
} |
2500 |
} |
| 2501 |
Inst.addOperand(MCOperand::createReg(RegNum)); |
2501 |
Inst.addOperand(MCOperand::createReg(RegNum)); |
| 2502 |
} |
2502 |
} |
| 2503 |
|
2503 |
|
| 2504 |
void addCoprocNumOperands(MCInst &Inst, unsigned N) const { |
2504 |
void addCoprocNumOperands(MCInst &Inst, unsigned N) const { |
| 2505 |
assert(N == 1 && "Invalid number of operands!"); |
2505 |
assert(N == 1 && "Invalid number of operands!"); |
| 2506 |
Inst.addOperand(MCOperand::createImm(getCoproc())); |
2506 |
Inst.addOperand(MCOperand::createImm(getCoproc())); |
| 2507 |
} |
2507 |
} |
| 2508 |
|
2508 |
|
| 2509 |
void addCoprocRegOperands(MCInst &Inst, unsigned N) const { |
2509 |
void addCoprocRegOperands(MCInst &Inst, unsigned N) const { |
| 2510 |
assert(N == 1 && "Invalid number of operands!"); |
2510 |
assert(N == 1 && "Invalid number of operands!"); |
| 2511 |
Inst.addOperand(MCOperand::createImm(getCoproc())); |
2511 |
Inst.addOperand(MCOperand::createImm(getCoproc())); |
| 2512 |
} |
2512 |
} |
| 2513 |
|
2513 |
|
| 2514 |
void addCoprocOptionOperands(MCInst &Inst, unsigned N) const { |
2514 |
void addCoprocOptionOperands(MCInst &Inst, unsigned N) const { |
| 2515 |
assert(N == 1 && "Invalid number of operands!"); |
2515 |
assert(N == 1 && "Invalid number of operands!"); |
| 2516 |
Inst.addOperand(MCOperand::createImm(CoprocOption.Val)); |
2516 |
Inst.addOperand(MCOperand::createImm(CoprocOption.Val)); |
| 2517 |
} |
2517 |
} |
| 2518 |
|
2518 |
|
| 2519 |
void addITMaskOperands(MCInst &Inst, unsigned N) const { |
2519 |
void addITMaskOperands(MCInst &Inst, unsigned N) const { |
| 2520 |
assert(N == 1 && "Invalid number of operands!"); |
2520 |
assert(N == 1 && "Invalid number of operands!"); |
| 2521 |
Inst.addOperand(MCOperand::createImm(ITMask.Mask)); |
2521 |
Inst.addOperand(MCOperand::createImm(ITMask.Mask)); |
| 2522 |
} |
2522 |
} |
| 2523 |
|
2523 |
|
| 2524 |
void addITCondCodeOperands(MCInst &Inst, unsigned N) const { |
2524 |
void addITCondCodeOperands(MCInst &Inst, unsigned N) const { |
| 2525 |
assert(N == 1 && "Invalid number of operands!"); |
2525 |
assert(N == 1 && "Invalid number of operands!"); |
| 2526 |
Inst.addOperand(MCOperand::createImm(unsigned(getCondCode()))); |
2526 |
Inst.addOperand(MCOperand::createImm(unsigned(getCondCode()))); |
| 2527 |
} |
2527 |
} |
| 2528 |
|
2528 |
|
| 2529 |
void addITCondCodeInvOperands(MCInst &Inst, unsigned N) const { |
2529 |
void addITCondCodeInvOperands(MCInst &Inst, unsigned N) const { |
| 2530 |
assert(N == 1 && "Invalid number of operands!"); |
2530 |
assert(N == 1 && "Invalid number of operands!"); |
| 2531 |
Inst.addOperand(MCOperand::createImm(unsigned(ARMCC::getOppositeCondition(getCondCode())))); |
2531 |
Inst.addOperand(MCOperand::createImm(unsigned(ARMCC::getOppositeCondition(getCondCode())))); |
| 2532 |
} |
2532 |
} |
| 2533 |
|
2533 |
|
| 2534 |
void addCCOutOperands(MCInst &Inst, unsigned N) const { |
2534 |
void addCCOutOperands(MCInst &Inst, unsigned N) const { |
| 2535 |
assert(N == 1 && "Invalid number of operands!"); |
2535 |
assert(N == 1 && "Invalid number of operands!"); |
| 2536 |
Inst.addOperand(MCOperand::createReg(getReg())); |
2536 |
Inst.addOperand(MCOperand::createReg(getReg())); |
| 2537 |
} |
2537 |
} |
| 2538 |
|
2538 |
|
| 2539 |
void addRegOperands(MCInst &Inst, unsigned N) const { |
2539 |
void addRegOperands(MCInst &Inst, unsigned N) const { |
| 2540 |
assert(N == 1 && "Invalid number of operands!"); |
2540 |
assert(N == 1 && "Invalid number of operands!"); |
| 2541 |
Inst.addOperand(MCOperand::createReg(getReg())); |
2541 |
Inst.addOperand(MCOperand::createReg(getReg())); |
| 2542 |
} |
2542 |
} |
| 2543 |
|
2543 |
|
| 2544 |
void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const { |
2544 |
void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const { |
| 2545 |
assert(N == 3 && "Invalid number of operands!"); |
2545 |
assert(N == 3 && "Invalid number of operands!"); |
| 2546 |
assert(isRegShiftedReg() && |
2546 |
assert(isRegShiftedReg() && |
| 2547 |
"addRegShiftedRegOperands() on non-RegShiftedReg!"); |
2547 |
"addRegShiftedRegOperands() on non-RegShiftedReg!"); |
| 2548 |
Inst.addOperand(MCOperand::createReg(RegShiftedReg.SrcReg)); |
2548 |
Inst.addOperand(MCOperand::createReg(RegShiftedReg.SrcReg)); |
| 2549 |
Inst.addOperand(MCOperand::createReg(RegShiftedReg.ShiftReg)); |
2549 |
Inst.addOperand(MCOperand::createReg(RegShiftedReg.ShiftReg)); |
| 2550 |
Inst.addOperand(MCOperand::createImm( |
2550 |
Inst.addOperand(MCOperand::createImm( |
| 2551 |
ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm))); |
2551 |
ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm))); |
| 2552 |
} |
2552 |
} |
| 2553 |
|
2553 |
|
| 2554 |
void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const { |
2554 |
void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const { |
| 2555 |
assert(N == 2 && "Invalid number of operands!"); |
2555 |
assert(N == 2 && "Invalid number of operands!"); |
| 2556 |
assert(isRegShiftedImm() && |
2556 |
assert(isRegShiftedImm() && |
| 2557 |
"addRegShiftedImmOperands() on non-RegShiftedImm!"); |
2557 |
"addRegShiftedImmOperands() on non-RegShiftedImm!"); |
| 2558 |
Inst.addOperand(MCOperand::createReg(RegShiftedImm.SrcReg)); |
2558 |
Inst.addOperand(MCOperand::createReg(RegShiftedImm.SrcReg)); |
| 2559 |
// Shift of #32 is encoded as 0 where permitted |
2559 |
// Shift of #32 is encoded as 0 where permitted |
| 2560 |
unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm); |
2560 |
unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm); |
| 2561 |
Inst.addOperand(MCOperand::createImm( |
2561 |
Inst.addOperand(MCOperand::createImm( |
| 2562 |
ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm))); |
2562 |
ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm))); |
| 2563 |
} |
2563 |
} |
| 2564 |
|
2564 |
|
| 2565 |
void addShifterImmOperands(MCInst &Inst, unsigned N) const { |
2565 |
void addShifterImmOperands(MCInst &Inst, unsigned N) const { |
| 2566 |
assert(N == 1 && "Invalid number of operands!"); |
2566 |
assert(N == 1 && "Invalid number of operands!"); |
| 2567 |
Inst.addOperand(MCOperand::createImm((ShifterImm.isASR << 5) | |
2567 |
Inst.addOperand(MCOperand::createImm((ShifterImm.isASR << 5) | |
| 2568 |
ShifterImm.Imm)); |
2568 |
ShifterImm.Imm)); |
| 2569 |
} |
2569 |
} |
| 2570 |
|
2570 |
|
| 2571 |
void addRegListOperands(MCInst &Inst, unsigned N) const { |
2571 |
void addRegListOperands(MCInst &Inst, unsigned N) const { |
| 2572 |
assert(N == 1 && "Invalid number of operands!"); |
2572 |
assert(N == 1 && "Invalid number of operands!"); |
| 2573 |
const SmallVectorImpl &RegList = getRegList(); |
2573 |
const SmallVectorImpl &RegList = getRegList(); |
| 2574 |
for (unsigned Reg : RegList) |
2574 |
for (unsigned Reg : RegList) |
| 2575 |
Inst.addOperand(MCOperand::createReg(Reg)); |
2575 |
Inst.addOperand(MCOperand::createReg(Reg)); |
| 2576 |
} |
2576 |
} |
| 2577 |
|
2577 |
|
| 2578 |
void addRegListWithAPSROperands(MCInst &Inst, unsigned N) const { |
2578 |
void addRegListWithAPSROperands(MCInst &Inst, unsigned N) const { |
| 2579 |
assert(N == 1 && "Invalid number of operands!"); |
2579 |
assert(N == 1 && "Invalid number of operands!"); |
| 2580 |
const SmallVectorImpl &RegList = getRegList(); |
2580 |
const SmallVectorImpl &RegList = getRegList(); |
| 2581 |
for (unsigned Reg : RegList) |
2581 |
for (unsigned Reg : RegList) |
| 2582 |
Inst.addOperand(MCOperand::createReg(Reg)); |
2582 |
Inst.addOperand(MCOperand::createReg(Reg)); |
| 2583 |
} |
2583 |
} |
| 2584 |
|
2584 |
|
| 2585 |
void addDPRRegListOperands(MCInst &Inst, unsigned N) const { |
2585 |
void addDPRRegListOperands(MCInst &Inst, unsigned N) const { |
| 2586 |
addRegListOperands(Inst, N); |
2586 |
addRegListOperands(Inst, N); |
| 2587 |
} |
2587 |
} |
| 2588 |
|
2588 |
|
| 2589 |
void addSPRRegListOperands(MCInst &Inst, unsigned N) const { |
2589 |
void addSPRRegListOperands(MCInst &Inst, unsigned N) const { |
| 2590 |
addRegListOperands(Inst, N); |
2590 |
addRegListOperands(Inst, N); |
| 2591 |
} |
2591 |
} |
| 2592 |
|
2592 |
|
| 2593 |
void addFPSRegListWithVPROperands(MCInst &Inst, unsigned N) const { |
2593 |
void addFPSRegListWithVPROperands(MCInst &Inst, unsigned N) const { |
| 2594 |
addRegListOperands(Inst, N); |
2594 |
addRegListOperands(Inst, N); |
| 2595 |
} |
2595 |
} |
| 2596 |
|
2596 |
|
| 2597 |
void addFPDRegListWithVPROperands(MCInst &Inst, unsigned N) const { |
2597 |
void addFPDRegListWithVPROperands(MCInst &Inst, unsigned N) const { |
| 2598 |
addRegListOperands(Inst, N); |
2598 |
addRegListOperands(Inst, N); |
| 2599 |
} |
2599 |
} |
| 2600 |
|
2600 |
|
| 2601 |
void addRotImmOperands(MCInst &Inst, unsigned N) const { |
2601 |
void addRotImmOperands(MCInst &Inst, unsigned N) const { |
| 2602 |
assert(N == 1 && "Invalid number of operands!"); |
2602 |
assert(N == 1 && "Invalid number of operands!"); |
| 2603 |
// Encoded as val>>3. The printer handles display as 8, 16, 24. |
2603 |
// Encoded as val>>3. The printer handles display as 8, 16, 24. |
| 2604 |
Inst.addOperand(MCOperand::createImm(RotImm.Imm >> 3)); |
2604 |
Inst.addOperand(MCOperand::createImm(RotImm.Imm >> 3)); |
| 2605 |
} |
2605 |
} |
| 2606 |
|
2606 |
|
| 2607 |
void addModImmOperands(MCInst &Inst, unsigned N) const { |
2607 |
void addModImmOperands(MCInst &Inst, unsigned N) const { |
| 2608 |
assert(N == 1 && "Invalid number of operands!"); |
2608 |
assert(N == 1 && "Invalid number of operands!"); |
| 2609 |
|
2609 |
|
| 2610 |
// Support for fixups (MCFixup) |
2610 |
// Support for fixups (MCFixup) |
| 2611 |
if (isImm()) |
2611 |
if (isImm()) |
| 2612 |
return addImmOperands(Inst, N); |
2612 |
return addImmOperands(Inst, N); |
| 2613 |
|
2613 |
|
| 2614 |
Inst.addOperand(MCOperand::createImm(ModImm.Bits | (ModImm.Rot << 7))); |
2614 |
Inst.addOperand(MCOperand::createImm(ModImm.Bits | (ModImm.Rot << 7))); |
| 2615 |
} |
2615 |
} |
| 2616 |
|
2616 |
|
| 2617 |
void addModImmNotOperands(MCInst &Inst, unsigned N) const { |
2617 |
void addModImmNotOperands(MCInst &Inst, unsigned N) const { |
| 2618 |
assert(N == 1 && "Invalid number of operands!"); |
2618 |
assert(N == 1 && "Invalid number of operands!"); |
| 2619 |
const MCConstantExpr *CE = cast(getImm()); |
2619 |
const MCConstantExpr *CE = cast(getImm()); |
| 2620 |
uint32_t Enc = ARM_AM::getSOImmVal(~CE->getValue()); |
2620 |
uint32_t Enc = ARM_AM::getSOImmVal(~CE->getValue()); |
| 2621 |
Inst.addOperand(MCOperand::createImm(Enc)); |
2621 |
Inst.addOperand(MCOperand::createImm(Enc)); |
| 2622 |
} |
2622 |
} |
| 2623 |
|
2623 |
|
| 2624 |
void addModImmNegOperands(MCInst &Inst, unsigned N) const { |
2624 |
void addModImmNegOperands(MCInst &Inst, unsigned N) const { |
| 2625 |
assert(N == 1 && "Invalid number of operands!"); |
2625 |
assert(N == 1 && "Invalid number of operands!"); |
| 2626 |
const MCConstantExpr *CE = cast(getImm()); |
2626 |
const MCConstantExpr *CE = cast(getImm()); |
| 2627 |
uint32_t Enc = ARM_AM::getSOImmVal(-CE->getValue()); |
2627 |
uint32_t Enc = ARM_AM::getSOImmVal(-CE->getValue()); |
| 2628 |
Inst.addOperand(MCOperand::createImm(Enc)); |
2628 |
Inst.addOperand(MCOperand::createImm(Enc)); |
| 2629 |
} |
2629 |
} |
| 2630 |
|
2630 |
|
| 2631 |
void addThumbModImmNeg8_255Operands(MCInst &Inst, unsigned N) const { |
2631 |
void addThumbModImmNeg8_255Operands(MCInst &Inst, unsigned N) const { |
| 2632 |
assert(N == 1 && "Invalid number of operands!"); |
2632 |
assert(N == 1 && "Invalid number of operands!"); |
| 2633 |
const MCConstantExpr *CE = cast(getImm()); |
2633 |
const MCConstantExpr *CE = cast(getImm()); |
| 2634 |
uint32_t Val = -CE->getValue(); |
2634 |
uint32_t Val = -CE->getValue(); |
| 2635 |
Inst.addOperand(MCOperand::createImm(Val)); |
2635 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 2636 |
} |
2636 |
} |
| 2637 |
|
2637 |
|
| 2638 |
void addThumbModImmNeg1_7Operands(MCInst &Inst, unsigned N) const { |
2638 |
void addThumbModImmNeg1_7Operands(MCInst &Inst, unsigned N) const { |
| 2639 |
assert(N == 1 && "Invalid number of operands!"); |
2639 |
assert(N == 1 && "Invalid number of operands!"); |
| 2640 |
const MCConstantExpr *CE = cast(getImm()); |
2640 |
const MCConstantExpr *CE = cast(getImm()); |
| 2641 |
uint32_t Val = -CE->getValue(); |
2641 |
uint32_t Val = -CE->getValue(); |
| 2642 |
Inst.addOperand(MCOperand::createImm(Val)); |
2642 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 2643 |
} |
2643 |
} |
| 2644 |
|
2644 |
|
| 2645 |
void addBitfieldOperands(MCInst &Inst, unsigned N) const { |
2645 |
void addBitfieldOperands(MCInst &Inst, unsigned N) const { |
| 2646 |
assert(N == 1 && "Invalid number of operands!"); |
2646 |
assert(N == 1 && "Invalid number of operands!"); |
| 2647 |
// Munge the lsb/width into a bitfield mask. |
2647 |
// Munge the lsb/width into a bitfield mask. |
| 2648 |
unsigned lsb = Bitfield.LSB; |
2648 |
unsigned lsb = Bitfield.LSB; |
| 2649 |
unsigned width = Bitfield.Width; |
2649 |
unsigned width = Bitfield.Width; |
| 2650 |
// Make a 32-bit mask w/ the referenced bits clear and all other bits set. |
2650 |
// Make a 32-bit mask w/ the referenced bits clear and all other bits set. |
| 2651 |
uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >> |
2651 |
uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >> |
| 2652 |
(32 - (lsb + width))); |
2652 |
(32 - (lsb + width))); |
| 2653 |
Inst.addOperand(MCOperand::createImm(Mask)); |
2653 |
Inst.addOperand(MCOperand::createImm(Mask)); |
| 2654 |
} |
2654 |
} |
| 2655 |
|
2655 |
|
| 2656 |
void addImmOperands(MCInst &Inst, unsigned N) const { |
2656 |
void addImmOperands(MCInst &Inst, unsigned N) const { |
| 2657 |
assert(N == 1 && "Invalid number of operands!"); |
2657 |
assert(N == 1 && "Invalid number of operands!"); |
| 2658 |
addExpr(Inst, getImm()); |
2658 |
addExpr(Inst, getImm()); |
| 2659 |
} |
2659 |
} |
| 2660 |
|
2660 |
|
| 2661 |
void addFBits16Operands(MCInst &Inst, unsigned N) const { |
2661 |
void addFBits16Operands(MCInst &Inst, unsigned N) const { |
| 2662 |
assert(N == 1 && "Invalid number of operands!"); |
2662 |
assert(N == 1 && "Invalid number of operands!"); |
| 2663 |
const MCConstantExpr *CE = cast(getImm()); |
2663 |
const MCConstantExpr *CE = cast(getImm()); |
| 2664 |
Inst.addOperand(MCOperand::createImm(16 - CE->getValue())); |
2664 |
Inst.addOperand(MCOperand::createImm(16 - CE->getValue())); |
| 2665 |
} |
2665 |
} |
| 2666 |
|
2666 |
|
| 2667 |
void addFBits32Operands(MCInst &Inst, unsigned N) const { |
2667 |
void addFBits32Operands(MCInst &Inst, unsigned N) const { |
| 2668 |
assert(N == 1 && "Invalid number of operands!"); |
2668 |
assert(N == 1 && "Invalid number of operands!"); |
| 2669 |
const MCConstantExpr *CE = cast(getImm()); |
2669 |
const MCConstantExpr *CE = cast(getImm()); |
| 2670 |
Inst.addOperand(MCOperand::createImm(32 - CE->getValue())); |
2670 |
Inst.addOperand(MCOperand::createImm(32 - CE->getValue())); |
| 2671 |
} |
2671 |
} |
| 2672 |
|
2672 |
|
| 2673 |
void addFPImmOperands(MCInst &Inst, unsigned N) const { |
2673 |
void addFPImmOperands(MCInst &Inst, unsigned N) const { |
| 2674 |
assert(N == 1 && "Invalid number of operands!"); |
2674 |
assert(N == 1 && "Invalid number of operands!"); |
| 2675 |
const MCConstantExpr *CE = cast(getImm()); |
2675 |
const MCConstantExpr *CE = cast(getImm()); |
| 2676 |
int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); |
2676 |
int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); |
| 2677 |
Inst.addOperand(MCOperand::createImm(Val)); |
2677 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 2678 |
} |
2678 |
} |
| 2679 |
|
2679 |
|
| 2680 |
void addImm8s4Operands(MCInst &Inst, unsigned N) const { |
2680 |
void addImm8s4Operands(MCInst &Inst, unsigned N) const { |
| 2681 |
assert(N == 1 && "Invalid number of operands!"); |
2681 |
assert(N == 1 && "Invalid number of operands!"); |
| 2682 |
// FIXME: We really want to scale the value here, but the LDRD/STRD |
2682 |
// FIXME: We really want to scale the value here, but the LDRD/STRD |
| 2683 |
// instruction don't encode operands that way yet. |
2683 |
// instruction don't encode operands that way yet. |
| 2684 |
const MCConstantExpr *CE = cast(getImm()); |
2684 |
const MCConstantExpr *CE = cast(getImm()); |
| 2685 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
2685 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 2686 |
} |
2686 |
} |
| 2687 |
|
2687 |
|
| 2688 |
void addImm7s4Operands(MCInst &Inst, unsigned N) const { |
2688 |
void addImm7s4Operands(MCInst &Inst, unsigned N) const { |
| 2689 |
assert(N == 1 && "Invalid number of operands!"); |
2689 |
assert(N == 1 && "Invalid number of operands!"); |
| 2690 |
// FIXME: We really want to scale the value here, but the VSTR/VLDR_VSYSR |
2690 |
// FIXME: We really want to scale the value here, but the VSTR/VLDR_VSYSR |
| 2691 |
// instruction don't encode operands that way yet. |
2691 |
// instruction don't encode operands that way yet. |
| 2692 |
const MCConstantExpr *CE = cast(getImm()); |
2692 |
const MCConstantExpr *CE = cast(getImm()); |
| 2693 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
2693 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 2694 |
} |
2694 |
} |
| 2695 |
|
2695 |
|
| 2696 |
void addImm7Shift0Operands(MCInst &Inst, unsigned N) const { |
2696 |
void addImm7Shift0Operands(MCInst &Inst, unsigned N) const { |
| 2697 |
assert(N == 1 && "Invalid number of operands!"); |
2697 |
assert(N == 1 && "Invalid number of operands!"); |
| 2698 |
const MCConstantExpr *CE = cast(getImm()); |
2698 |
const MCConstantExpr *CE = cast(getImm()); |
| 2699 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
2699 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 2700 |
} |
2700 |
} |
| 2701 |
|
2701 |
|
| 2702 |
void addImm7Shift1Operands(MCInst &Inst, unsigned N) const { |
2702 |
void addImm7Shift1Operands(MCInst &Inst, unsigned N) const { |
| 2703 |
assert(N == 1 && "Invalid number of operands!"); |
2703 |
assert(N == 1 && "Invalid number of operands!"); |
| 2704 |
const MCConstantExpr *CE = cast(getImm()); |
2704 |
const MCConstantExpr *CE = cast(getImm()); |
| 2705 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
2705 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 2706 |
} |
2706 |
} |
| 2707 |
|
2707 |
|
| 2708 |
void addImm7Shift2Operands(MCInst &Inst, unsigned N) const { |
2708 |
void addImm7Shift2Operands(MCInst &Inst, unsigned N) const { |
| 2709 |
assert(N == 1 && "Invalid number of operands!"); |
2709 |
assert(N == 1 && "Invalid number of operands!"); |
| 2710 |
const MCConstantExpr *CE = cast(getImm()); |
2710 |
const MCConstantExpr *CE = cast(getImm()); |
| 2711 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
2711 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 2712 |
} |
2712 |
} |
| 2713 |
|
2713 |
|
| 2714 |
void addImm7Operands(MCInst &Inst, unsigned N) const { |
2714 |
void addImm7Operands(MCInst &Inst, unsigned N) const { |
| 2715 |
assert(N == 1 && "Invalid number of operands!"); |
2715 |
assert(N == 1 && "Invalid number of operands!"); |
| 2716 |
const MCConstantExpr *CE = cast(getImm()); |
2716 |
const MCConstantExpr *CE = cast(getImm()); |
| 2717 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
2717 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 2718 |
} |
2718 |
} |
| 2719 |
|
2719 |
|
| 2720 |
void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const { |
2720 |
void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const { |
| 2721 |
assert(N == 1 && "Invalid number of operands!"); |
2721 |
assert(N == 1 && "Invalid number of operands!"); |
| 2722 |
// The immediate is scaled by four in the encoding and is stored |
2722 |
// The immediate is scaled by four in the encoding and is stored |
| 2723 |
// in the MCInst as such. Lop off the low two bits here. |
2723 |
// in the MCInst as such. Lop off the low two bits here. |
| 2724 |
const MCConstantExpr *CE = cast(getImm()); |
2724 |
const MCConstantExpr *CE = cast(getImm()); |
| 2725 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); |
2725 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); |
| 2726 |
} |
2726 |
} |
| 2727 |
|
2727 |
|
| 2728 |
void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const { |
2728 |
void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const { |
| 2729 |
assert(N == 1 && "Invalid number of operands!"); |
2729 |
assert(N == 1 && "Invalid number of operands!"); |
| 2730 |
// The immediate is scaled by four in the encoding and is stored |
2730 |
// The immediate is scaled by four in the encoding and is stored |
| 2731 |
// in the MCInst as such. Lop off the low two bits here. |
2731 |
// in the MCInst as such. Lop off the low two bits here. |
| 2732 |
const MCConstantExpr *CE = cast(getImm()); |
2732 |
const MCConstantExpr *CE = cast(getImm()); |
| 2733 |
Inst.addOperand(MCOperand::createImm(-(CE->getValue() / 4))); |
2733 |
Inst.addOperand(MCOperand::createImm(-(CE->getValue() / 4))); |
| 2734 |
} |
2734 |
} |
| 2735 |
|
2735 |
|
| 2736 |
void addImm0_508s4Operands(MCInst &Inst, unsigned N) const { |
2736 |
void addImm0_508s4Operands(MCInst &Inst, unsigned N) const { |
| 2737 |
assert(N == 1 && "Invalid number of operands!"); |
2737 |
assert(N == 1 && "Invalid number of operands!"); |
| 2738 |
// The immediate is scaled by four in the encoding and is stored |
2738 |
// The immediate is scaled by four in the encoding and is stored |
| 2739 |
// in the MCInst as such. Lop off the low two bits here. |
2739 |
// in the MCInst as such. Lop off the low two bits here. |
| 2740 |
const MCConstantExpr *CE = cast(getImm()); |
2740 |
const MCConstantExpr *CE = cast(getImm()); |
| 2741 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); |
2741 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); |
| 2742 |
} |
2742 |
} |
| 2743 |
|
2743 |
|
| 2744 |
void addImm1_16Operands(MCInst &Inst, unsigned N) const { |
2744 |
void addImm1_16Operands(MCInst &Inst, unsigned N) const { |
| 2745 |
assert(N == 1 && "Invalid number of operands!"); |
2745 |
assert(N == 1 && "Invalid number of operands!"); |
| 2746 |
// The constant encodes as the immediate-1, and we store in the instruction |
2746 |
// The constant encodes as the immediate-1, and we store in the instruction |
| 2747 |
// the bits as encoded, so subtract off one here. |
2747 |
// the bits as encoded, so subtract off one here. |
| 2748 |
const MCConstantExpr *CE = cast(getImm()); |
2748 |
const MCConstantExpr *CE = cast(getImm()); |
| 2749 |
Inst.addOperand(MCOperand::createImm(CE->getValue() - 1)); |
2749 |
Inst.addOperand(MCOperand::createImm(CE->getValue() - 1)); |
| 2750 |
} |
2750 |
} |
| 2751 |
|
2751 |
|
| 2752 |
void addImm1_32Operands(MCInst &Inst, unsigned N) const { |
2752 |
void addImm1_32Operands(MCInst &Inst, unsigned N) const { |
| 2753 |
assert(N == 1 && "Invalid number of operands!"); |
2753 |
assert(N == 1 && "Invalid number of operands!"); |
| 2754 |
// The constant encodes as the immediate-1, and we store in the instruction |
2754 |
// The constant encodes as the immediate-1, and we store in the instruction |
| 2755 |
// the bits as encoded, so subtract off one here. |
2755 |
// the bits as encoded, so subtract off one here. |
| 2756 |
const MCConstantExpr *CE = cast(getImm()); |
2756 |
const MCConstantExpr *CE = cast(getImm()); |
| 2757 |
Inst.addOperand(MCOperand::createImm(CE->getValue() - 1)); |
2757 |
Inst.addOperand(MCOperand::createImm(CE->getValue() - 1)); |
| 2758 |
} |
2758 |
} |
| 2759 |
|
2759 |
|
| 2760 |
void addImmThumbSROperands(MCInst &Inst, unsigned N) const { |
2760 |
void addImmThumbSROperands(MCInst &Inst, unsigned N) const { |
| 2761 |
assert(N == 1 && "Invalid number of operands!"); |
2761 |
assert(N == 1 && "Invalid number of operands!"); |
| 2762 |
// The constant encodes as the immediate, except for 32, which encodes as |
2762 |
// The constant encodes as the immediate, except for 32, which encodes as |
| 2763 |
// zero. |
2763 |
// zero. |
| 2764 |
const MCConstantExpr *CE = cast(getImm()); |
2764 |
const MCConstantExpr *CE = cast(getImm()); |
| 2765 |
unsigned Imm = CE->getValue(); |
2765 |
unsigned Imm = CE->getValue(); |
| 2766 |
Inst.addOperand(MCOperand::createImm((Imm == 32 ? 0 : Imm))); |
2766 |
Inst.addOperand(MCOperand::createImm((Imm == 32 ? 0 : Imm))); |
| 2767 |
} |
2767 |
} |
| 2768 |
|
2768 |
|
| 2769 |
void addPKHASRImmOperands(MCInst &Inst, unsigned N) const { |
2769 |
void addPKHASRImmOperands(MCInst &Inst, unsigned N) const { |
| 2770 |
assert(N == 1 && "Invalid number of operands!"); |
2770 |
assert(N == 1 && "Invalid number of operands!"); |
| 2771 |
// An ASR value of 32 encodes as 0, so that's how we want to add it to |
2771 |
// An ASR value of 32 encodes as 0, so that's how we want to add it to |
| 2772 |
// the instruction as well. |
2772 |
// the instruction as well. |
| 2773 |
const MCConstantExpr *CE = cast(getImm()); |
2773 |
const MCConstantExpr *CE = cast(getImm()); |
| 2774 |
int Val = CE->getValue(); |
2774 |
int Val = CE->getValue(); |
| 2775 |
Inst.addOperand(MCOperand::createImm(Val == 32 ? 0 : Val)); |
2775 |
Inst.addOperand(MCOperand::createImm(Val == 32 ? 0 : Val)); |
| 2776 |
} |
2776 |
} |
| 2777 |
|
2777 |
|
| 2778 |
void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const { |
2778 |
void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const { |
| 2779 |
assert(N == 1 && "Invalid number of operands!"); |
2779 |
assert(N == 1 && "Invalid number of operands!"); |
| 2780 |
// The operand is actually a t2_so_imm, but we have its bitwise |
2780 |
// The operand is actually a t2_so_imm, but we have its bitwise |
| 2781 |
// negation in the assembly source, so twiddle it here. |
2781 |
// negation in the assembly source, so twiddle it here. |
| 2782 |
const MCConstantExpr *CE = cast(getImm()); |
2782 |
const MCConstantExpr *CE = cast(getImm()); |
| 2783 |
Inst.addOperand(MCOperand::createImm(~(uint32_t)CE->getValue())); |
2783 |
Inst.addOperand(MCOperand::createImm(~(uint32_t)CE->getValue())); |
| 2784 |
} |
2784 |
} |
| 2785 |
|
2785 |
|
| 2786 |
void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const { |
2786 |
void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const { |
| 2787 |
assert(N == 1 && "Invalid number of operands!"); |
2787 |
assert(N == 1 && "Invalid number of operands!"); |
| 2788 |
// The operand is actually a t2_so_imm, but we have its |
2788 |
// The operand is actually a t2_so_imm, but we have its |
| 2789 |
// negation in the assembly source, so twiddle it here. |
2789 |
// negation in the assembly source, so twiddle it here. |
| 2790 |
const MCConstantExpr *CE = cast(getImm()); |
2790 |
const MCConstantExpr *CE = cast(getImm()); |
| 2791 |
Inst.addOperand(MCOperand::createImm(-(uint32_t)CE->getValue())); |
2791 |
Inst.addOperand(MCOperand::createImm(-(uint32_t)CE->getValue())); |
| 2792 |
} |
2792 |
} |
| 2793 |
|
2793 |
|
| 2794 |
void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const { |
2794 |
void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const { |
| 2795 |
assert(N == 1 && "Invalid number of operands!"); |
2795 |
assert(N == 1 && "Invalid number of operands!"); |
| 2796 |
// The operand is actually an imm0_4095, but we have its |
2796 |
// The operand is actually an imm0_4095, but we have its |
| 2797 |
// negation in the assembly source, so twiddle it here. |
2797 |
// negation in the assembly source, so twiddle it here. |
| 2798 |
const MCConstantExpr *CE = cast(getImm()); |
2798 |
const MCConstantExpr *CE = cast(getImm()); |
| 2799 |
Inst.addOperand(MCOperand::createImm(-(uint32_t)CE->getValue())); |
2799 |
Inst.addOperand(MCOperand::createImm(-(uint32_t)CE->getValue())); |
| 2800 |
} |
2800 |
} |
| 2801 |
|
2801 |
|
| 2802 |
void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const { |
2802 |
void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const { |
| 2803 |
if(const MCConstantExpr *CE = dyn_cast(getImm())) { |
2803 |
if(const MCConstantExpr *CE = dyn_cast(getImm())) { |
| 2804 |
Inst.addOperand(MCOperand::createImm(CE->getValue() >> 2)); |
2804 |
Inst.addOperand(MCOperand::createImm(CE->getValue() >> 2)); |
| 2805 |
return; |
2805 |
return; |
| 2806 |
} |
2806 |
} |
| 2807 |
const MCSymbolRefExpr *SR = cast(Imm.Val); |
2807 |
const MCSymbolRefExpr *SR = cast(Imm.Val); |
| 2808 |
Inst.addOperand(MCOperand::createExpr(SR)); |
2808 |
Inst.addOperand(MCOperand::createExpr(SR)); |
| 2809 |
} |
2809 |
} |
| 2810 |
|
2810 |
|
| 2811 |
void addThumbMemPCOperands(MCInst &Inst, unsigned N) const { |
2811 |
void addThumbMemPCOperands(MCInst &Inst, unsigned N) const { |
| 2812 |
assert(N == 1 && "Invalid number of operands!"); |
2812 |
assert(N == 1 && "Invalid number of operands!"); |
| 2813 |
if (isImm()) { |
2813 |
if (isImm()) { |
| 2814 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2814 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2815 |
if (CE) { |
2815 |
if (CE) { |
| 2816 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
2816 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 2817 |
return; |
2817 |
return; |
| 2818 |
} |
2818 |
} |
| 2819 |
const MCSymbolRefExpr *SR = cast(Imm.Val); |
2819 |
const MCSymbolRefExpr *SR = cast(Imm.Val); |
| 2820 |
Inst.addOperand(MCOperand::createExpr(SR)); |
2820 |
Inst.addOperand(MCOperand::createExpr(SR)); |
| 2821 |
return; |
2821 |
return; |
| 2822 |
} |
2822 |
} |
| 2823 |
|
2823 |
|
| 2824 |
assert(isGPRMem() && "Unknown value type!"); |
2824 |
assert(isGPRMem() && "Unknown value type!"); |
| 2825 |
assert(isa(Memory.OffsetImm) && "Unknown value type!"); |
2825 |
assert(isa(Memory.OffsetImm) && "Unknown value type!"); |
| 2826 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
2826 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
| 2827 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
2827 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 2828 |
else |
2828 |
else |
| 2829 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
2829 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
| 2830 |
} |
2830 |
} |
| 2831 |
|
2831 |
|
| 2832 |
void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const { |
2832 |
void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const { |
| 2833 |
assert(N == 1 && "Invalid number of operands!"); |
2833 |
assert(N == 1 && "Invalid number of operands!"); |
| 2834 |
Inst.addOperand(MCOperand::createImm(unsigned(getMemBarrierOpt()))); |
2834 |
Inst.addOperand(MCOperand::createImm(unsigned(getMemBarrierOpt()))); |
| 2835 |
} |
2835 |
} |
| 2836 |
|
2836 |
|
| 2837 |
void addInstSyncBarrierOptOperands(MCInst &Inst, unsigned N) const { |
2837 |
void addInstSyncBarrierOptOperands(MCInst &Inst, unsigned N) const { |
| 2838 |
assert(N == 1 && "Invalid number of operands!"); |
2838 |
assert(N == 1 && "Invalid number of operands!"); |
| 2839 |
Inst.addOperand(MCOperand::createImm(unsigned(getInstSyncBarrierOpt()))); |
2839 |
Inst.addOperand(MCOperand::createImm(unsigned(getInstSyncBarrierOpt()))); |
| 2840 |
} |
2840 |
} |
| 2841 |
|
2841 |
|
| 2842 |
void addTraceSyncBarrierOptOperands(MCInst &Inst, unsigned N) const { |
2842 |
void addTraceSyncBarrierOptOperands(MCInst &Inst, unsigned N) const { |
| 2843 |
assert(N == 1 && "Invalid number of operands!"); |
2843 |
assert(N == 1 && "Invalid number of operands!"); |
| 2844 |
Inst.addOperand(MCOperand::createImm(unsigned(getTraceSyncBarrierOpt()))); |
2844 |
Inst.addOperand(MCOperand::createImm(unsigned(getTraceSyncBarrierOpt()))); |
| 2845 |
} |
2845 |
} |
| 2846 |
|
2846 |
|
| 2847 |
void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const { |
2847 |
void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const { |
| 2848 |
assert(N == 1 && "Invalid number of operands!"); |
2848 |
assert(N == 1 && "Invalid number of operands!"); |
| 2849 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
2849 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 2850 |
} |
2850 |
} |
| 2851 |
|
2851 |
|
| 2852 |
void addMemNoOffsetT2Operands(MCInst &Inst, unsigned N) const { |
2852 |
void addMemNoOffsetT2Operands(MCInst &Inst, unsigned N) const { |
| 2853 |
assert(N == 1 && "Invalid number of operands!"); |
2853 |
assert(N == 1 && "Invalid number of operands!"); |
| 2854 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
2854 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 2855 |
} |
2855 |
} |
| 2856 |
|
2856 |
|
| 2857 |
void addMemNoOffsetT2NoSpOperands(MCInst &Inst, unsigned N) const { |
2857 |
void addMemNoOffsetT2NoSpOperands(MCInst &Inst, unsigned N) const { |
| 2858 |
assert(N == 1 && "Invalid number of operands!"); |
2858 |
assert(N == 1 && "Invalid number of operands!"); |
| 2859 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
2859 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 2860 |
} |
2860 |
} |
| 2861 |
|
2861 |
|
| 2862 |
void addMemNoOffsetTOperands(MCInst &Inst, unsigned N) const { |
2862 |
void addMemNoOffsetTOperands(MCInst &Inst, unsigned N) const { |
| 2863 |
assert(N == 1 && "Invalid number of operands!"); |
2863 |
assert(N == 1 && "Invalid number of operands!"); |
| 2864 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
2864 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 2865 |
} |
2865 |
} |
| 2866 |
|
2866 |
|
| 2867 |
void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const { |
2867 |
void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const { |
| 2868 |
assert(N == 1 && "Invalid number of operands!"); |
2868 |
assert(N == 1 && "Invalid number of operands!"); |
| 2869 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
2869 |
if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
| 2870 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
2870 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 2871 |
else |
2871 |
else |
| 2872 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
2872 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
| 2873 |
} |
2873 |
} |
| 2874 |
|
2874 |
|
| 2875 |
void addAdrLabelOperands(MCInst &Inst, unsigned N) const { |
2875 |
void addAdrLabelOperands(MCInst &Inst, unsigned N) const { |
| 2876 |
assert(N == 1 && "Invalid number of operands!"); |
2876 |
assert(N == 1 && "Invalid number of operands!"); |
| 2877 |
assert(isImm() && "Not an immediate!"); |
2877 |
assert(isImm() && "Not an immediate!"); |
| 2878 |
|
2878 |
|
| 2879 |
// If we have an immediate that's not a constant, treat it as a label |
2879 |
// If we have an immediate that's not a constant, treat it as a label |
| 2880 |
// reference needing a fixup. |
2880 |
// reference needing a fixup. |
| 2881 |
if (!isa(getImm())) { |
2881 |
if (!isa(getImm())) { |
| 2882 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
2882 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
| 2883 |
return; |
2883 |
return; |
| 2884 |
} |
2884 |
} |
| 2885 |
|
2885 |
|
| 2886 |
const MCConstantExpr *CE = cast(getImm()); |
2886 |
const MCConstantExpr *CE = cast(getImm()); |
| 2887 |
int Val = CE->getValue(); |
2887 |
int Val = CE->getValue(); |
| 2888 |
Inst.addOperand(MCOperand::createImm(Val)); |
2888 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 2889 |
} |
2889 |
} |
| 2890 |
|
2890 |
|
| 2891 |
void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const { |
2891 |
void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const { |
| 2892 |
assert(N == 2 && "Invalid number of operands!"); |
2892 |
assert(N == 2 && "Invalid number of operands!"); |
| 2893 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
2893 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 2894 |
Inst.addOperand(MCOperand::createImm(Memory.Alignment)); |
2894 |
Inst.addOperand(MCOperand::createImm(Memory.Alignment)); |
| 2895 |
} |
2895 |
} |
| 2896 |
|
2896 |
|
| 2897 |
void addDupAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const { |
2897 |
void addDupAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const { |
| 2898 |
addAlignedMemoryOperands(Inst, N); |
2898 |
addAlignedMemoryOperands(Inst, N); |
| 2899 |
} |
2899 |
} |
| 2900 |
|
2900 |
|
| 2901 |
void addAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const { |
2901 |
void addAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const { |
| 2902 |
addAlignedMemoryOperands(Inst, N); |
2902 |
addAlignedMemoryOperands(Inst, N); |
| 2903 |
} |
2903 |
} |
| 2904 |
|
2904 |
|
| 2905 |
void addAlignedMemory16Operands(MCInst &Inst, unsigned N) const { |
2905 |
void addAlignedMemory16Operands(MCInst &Inst, unsigned N) const { |
| 2906 |
addAlignedMemoryOperands(Inst, N); |
2906 |
addAlignedMemoryOperands(Inst, N); |
| 2907 |
} |
2907 |
} |
| 2908 |
|
2908 |
|
| 2909 |
void addDupAlignedMemory16Operands(MCInst &Inst, unsigned N) const { |
2909 |
void addDupAlignedMemory16Operands(MCInst &Inst, unsigned N) const { |
| 2910 |
addAlignedMemoryOperands(Inst, N); |
2910 |
addAlignedMemoryOperands(Inst, N); |
| 2911 |
} |
2911 |
} |
| 2912 |
|
2912 |
|
| 2913 |
void addAlignedMemory32Operands(MCInst &Inst, unsigned N) const { |
2913 |
void addAlignedMemory32Operands(MCInst &Inst, unsigned N) const { |
| 2914 |
addAlignedMemoryOperands(Inst, N); |
2914 |
addAlignedMemoryOperands(Inst, N); |
| 2915 |
} |
2915 |
} |
| 2916 |
|
2916 |
|
| 2917 |
void addDupAlignedMemory32Operands(MCInst &Inst, unsigned N) const { |
2917 |
void addDupAlignedMemory32Operands(MCInst &Inst, unsigned N) const { |
| 2918 |
addAlignedMemoryOperands(Inst, N); |
2918 |
addAlignedMemoryOperands(Inst, N); |
| 2919 |
} |
2919 |
} |
| 2920 |
|
2920 |
|
| 2921 |
void addAlignedMemory64Operands(MCInst &Inst, unsigned N) const { |
2921 |
void addAlignedMemory64Operands(MCInst &Inst, unsigned N) const { |
| 2922 |
addAlignedMemoryOperands(Inst, N); |
2922 |
addAlignedMemoryOperands(Inst, N); |
| 2923 |
} |
2923 |
} |
| 2924 |
|
2924 |
|
| 2925 |
void addDupAlignedMemory64Operands(MCInst &Inst, unsigned N) const { |
2925 |
void addDupAlignedMemory64Operands(MCInst &Inst, unsigned N) const { |
| 2926 |
addAlignedMemoryOperands(Inst, N); |
2926 |
addAlignedMemoryOperands(Inst, N); |
| 2927 |
} |
2927 |
} |
| 2928 |
|
2928 |
|
| 2929 |
void addAlignedMemory64or128Operands(MCInst &Inst, unsigned N) const { |
2929 |
void addAlignedMemory64or128Operands(MCInst &Inst, unsigned N) const { |
| 2930 |
addAlignedMemoryOperands(Inst, N); |
2930 |
addAlignedMemoryOperands(Inst, N); |
| 2931 |
} |
2931 |
} |
| 2932 |
|
2932 |
|
| 2933 |
void addDupAlignedMemory64or128Operands(MCInst &Inst, unsigned N) const { |
2933 |
void addDupAlignedMemory64or128Operands(MCInst &Inst, unsigned N) const { |
| 2934 |
addAlignedMemoryOperands(Inst, N); |
2934 |
addAlignedMemoryOperands(Inst, N); |
| 2935 |
} |
2935 |
} |
| 2936 |
|
2936 |
|
| 2937 |
void addAlignedMemory64or128or256Operands(MCInst &Inst, unsigned N) const { |
2937 |
void addAlignedMemory64or128or256Operands(MCInst &Inst, unsigned N) const { |
| 2938 |
addAlignedMemoryOperands(Inst, N); |
2938 |
addAlignedMemoryOperands(Inst, N); |
| 2939 |
} |
2939 |
} |
| 2940 |
|
2940 |
|
| 2941 |
void addAddrMode2Operands(MCInst &Inst, unsigned N) const { |
2941 |
void addAddrMode2Operands(MCInst &Inst, unsigned N) const { |
| 2942 |
assert(N == 3 && "Invalid number of operands!"); |
2942 |
assert(N == 3 && "Invalid number of operands!"); |
| 2943 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
2943 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 2944 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
2944 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
| 2945 |
if (!Memory.OffsetRegNum) { |
2945 |
if (!Memory.OffsetRegNum) { |
| 2946 |
if (!Memory.OffsetImm) |
2946 |
if (!Memory.OffsetImm) |
| 2947 |
Inst.addOperand(MCOperand::createImm(0)); |
2947 |
Inst.addOperand(MCOperand::createImm(0)); |
| 2948 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
2948 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 2949 |
int32_t Val = CE->getValue(); |
2949 |
int32_t Val = CE->getValue(); |
| 2950 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
2950 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
| 2951 |
// Special case for #-0 |
2951 |
// Special case for #-0 |
| 2952 |
if (Val == std::numeric_limits::min()) |
2952 |
if (Val == std::numeric_limits::min()) |
| 2953 |
Val = 0; |
2953 |
Val = 0; |
| 2954 |
if (Val < 0) |
2954 |
if (Val < 0) |
| 2955 |
Val = -Val; |
2955 |
Val = -Val; |
| 2956 |
Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); |
2956 |
Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); |
| 2957 |
Inst.addOperand(MCOperand::createImm(Val)); |
2957 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 2958 |
} else |
2958 |
} else |
| 2959 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
2959 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
| 2960 |
} else { |
2960 |
} else { |
| 2961 |
// For register offset, we encode the shift type and negation flag |
2961 |
// For register offset, we encode the shift type and negation flag |
| 2962 |
// here. |
2962 |
// here. |
| 2963 |
int32_t Val = |
2963 |
int32_t Val = |
| 2964 |
ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, |
2964 |
ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, |
| 2965 |
Memory.ShiftImm, Memory.ShiftType); |
2965 |
Memory.ShiftImm, Memory.ShiftType); |
| 2966 |
Inst.addOperand(MCOperand::createImm(Val)); |
2966 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 2967 |
} |
2967 |
} |
| 2968 |
} |
2968 |
} |
| 2969 |
|
2969 |
|
| 2970 |
void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const { |
2970 |
void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const { |
| 2971 |
assert(N == 2 && "Invalid number of operands!"); |
2971 |
assert(N == 2 && "Invalid number of operands!"); |
| 2972 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
2972 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 2973 |
assert(CE && "non-constant AM2OffsetImm operand!"); |
2973 |
assert(CE && "non-constant AM2OffsetImm operand!"); |
| 2974 |
int32_t Val = CE->getValue(); |
2974 |
int32_t Val = CE->getValue(); |
| 2975 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
2975 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
| 2976 |
// Special case for #-0 |
2976 |
// Special case for #-0 |
| 2977 |
if (Val == std::numeric_limits::min()) Val = 0; |
2977 |
if (Val == std::numeric_limits::min()) Val = 0; |
| 2978 |
if (Val < 0) Val = -Val; |
2978 |
if (Val < 0) Val = -Val; |
| 2979 |
Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); |
2979 |
Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); |
| 2980 |
Inst.addOperand(MCOperand::createReg(0)); |
2980 |
Inst.addOperand(MCOperand::createReg(0)); |
| 2981 |
Inst.addOperand(MCOperand::createImm(Val)); |
2981 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 2982 |
} |
2982 |
} |
| 2983 |
|
2983 |
|
| 2984 |
void addAddrMode3Operands(MCInst &Inst, unsigned N) const { |
2984 |
void addAddrMode3Operands(MCInst &Inst, unsigned N) const { |
| 2985 |
assert(N == 3 && "Invalid number of operands!"); |
2985 |
assert(N == 3 && "Invalid number of operands!"); |
| 2986 |
// If we have an immediate that's not a constant, treat it as a label |
2986 |
// If we have an immediate that's not a constant, treat it as a label |
| 2987 |
// reference needing a fixup. If it is a constant, it's something else |
2987 |
// reference needing a fixup. If it is a constant, it's something else |
| 2988 |
// and we reject it. |
2988 |
// and we reject it. |
| 2989 |
if (isImm()) { |
2989 |
if (isImm()) { |
| 2990 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
2990 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
| 2991 |
Inst.addOperand(MCOperand::createReg(0)); |
2991 |
Inst.addOperand(MCOperand::createReg(0)); |
| 2992 |
Inst.addOperand(MCOperand::createImm(0)); |
2992 |
Inst.addOperand(MCOperand::createImm(0)); |
| 2993 |
return; |
2993 |
return; |
| 2994 |
} |
2994 |
} |
| 2995 |
|
2995 |
|
| 2996 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
2996 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 2997 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
2997 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
| 2998 |
if (!Memory.OffsetRegNum) { |
2998 |
if (!Memory.OffsetRegNum) { |
| 2999 |
if (!Memory.OffsetImm) |
2999 |
if (!Memory.OffsetImm) |
| 3000 |
Inst.addOperand(MCOperand::createImm(0)); |
3000 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3001 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
3001 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 3002 |
int32_t Val = CE->getValue(); |
3002 |
int32_t Val = CE->getValue(); |
| 3003 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
3003 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
| 3004 |
// Special case for #-0 |
3004 |
// Special case for #-0 |
| 3005 |
if (Val == std::numeric_limits::min()) |
3005 |
if (Val == std::numeric_limits::min()) |
| 3006 |
Val = 0; |
3006 |
Val = 0; |
| 3007 |
if (Val < 0) |
3007 |
if (Val < 0) |
| 3008 |
Val = -Val; |
3008 |
Val = -Val; |
| 3009 |
Val = ARM_AM::getAM3Opc(AddSub, Val); |
3009 |
Val = ARM_AM::getAM3Opc(AddSub, Val); |
| 3010 |
Inst.addOperand(MCOperand::createImm(Val)); |
3010 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 3011 |
} else |
3011 |
} else |
| 3012 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
3012 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
| 3013 |
} else { |
3013 |
} else { |
| 3014 |
// For register offset, we encode the shift type and negation flag |
3014 |
// For register offset, we encode the shift type and negation flag |
| 3015 |
// here. |
3015 |
// here. |
| 3016 |
int32_t Val = |
3016 |
int32_t Val = |
| 3017 |
ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0); |
3017 |
ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0); |
| 3018 |
Inst.addOperand(MCOperand::createImm(Val)); |
3018 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 3019 |
} |
3019 |
} |
| 3020 |
} |
3020 |
} |
| 3021 |
|
3021 |
|
| 3022 |
void addAM3OffsetOperands(MCInst &Inst, unsigned N) const { |
3022 |
void addAM3OffsetOperands(MCInst &Inst, unsigned N) const { |
| 3023 |
assert(N == 2 && "Invalid number of operands!"); |
3023 |
assert(N == 2 && "Invalid number of operands!"); |
| 3024 |
if (Kind == k_PostIndexRegister) { |
3024 |
if (Kind == k_PostIndexRegister) { |
| 3025 |
int32_t Val = |
3025 |
int32_t Val = |
| 3026 |
ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0); |
3026 |
ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0); |
| 3027 |
Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum)); |
3027 |
Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum)); |
| 3028 |
Inst.addOperand(MCOperand::createImm(Val)); |
3028 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 3029 |
return; |
3029 |
return; |
| 3030 |
} |
3030 |
} |
| 3031 |
|
3031 |
|
| 3032 |
// Constant offset. |
3032 |
// Constant offset. |
| 3033 |
const MCConstantExpr *CE = static_cast(getImm()); |
3033 |
const MCConstantExpr *CE = static_cast(getImm()); |
| 3034 |
int32_t Val = CE->getValue(); |
3034 |
int32_t Val = CE->getValue(); |
| 3035 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
3035 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
| 3036 |
// Special case for #-0 |
3036 |
// Special case for #-0 |
| 3037 |
if (Val == std::numeric_limits::min()) Val = 0; |
3037 |
if (Val == std::numeric_limits::min()) Val = 0; |
| 3038 |
if (Val < 0) Val = -Val; |
3038 |
if (Val < 0) Val = -Val; |
| 3039 |
Val = ARM_AM::getAM3Opc(AddSub, Val); |
3039 |
Val = ARM_AM::getAM3Opc(AddSub, Val); |
| 3040 |
Inst.addOperand(MCOperand::createReg(0)); |
3040 |
Inst.addOperand(MCOperand::createReg(0)); |
| 3041 |
Inst.addOperand(MCOperand::createImm(Val)); |
3041 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 3042 |
} |
3042 |
} |
| 3043 |
|
3043 |
|
| 3044 |
void addAddrMode5Operands(MCInst &Inst, unsigned N) const { |
3044 |
void addAddrMode5Operands(MCInst &Inst, unsigned N) const { |
| 3045 |
assert(N == 2 && "Invalid number of operands!"); |
3045 |
assert(N == 2 && "Invalid number of operands!"); |
| 3046 |
// If we have an immediate that's not a constant, treat it as a label |
3046 |
// If we have an immediate that's not a constant, treat it as a label |
| 3047 |
// reference needing a fixup. If it is a constant, it's something else |
3047 |
// reference needing a fixup. If it is a constant, it's something else |
| 3048 |
// and we reject it. |
3048 |
// and we reject it. |
| 3049 |
if (isImm()) { |
3049 |
if (isImm()) { |
| 3050 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
3050 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
| 3051 |
Inst.addOperand(MCOperand::createImm(0)); |
3051 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3052 |
return; |
3052 |
return; |
| 3053 |
} |
3053 |
} |
| 3054 |
|
3054 |
|
| 3055 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3055 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3056 |
if (!Memory.OffsetImm) |
3056 |
if (!Memory.OffsetImm) |
| 3057 |
Inst.addOperand(MCOperand::createImm(0)); |
3057 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3058 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
3058 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 3059 |
// The lower two bits are always zero and as such are not encoded. |
3059 |
// The lower two bits are always zero and as such are not encoded. |
| 3060 |
int32_t Val = CE->getValue() / 4; |
3060 |
int32_t Val = CE->getValue() / 4; |
| 3061 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
3061 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
| 3062 |
// Special case for #-0 |
3062 |
// Special case for #-0 |
| 3063 |
if (Val == std::numeric_limits::min()) |
3063 |
if (Val == std::numeric_limits::min()) |
| 3064 |
Val = 0; |
3064 |
Val = 0; |
| 3065 |
if (Val < 0) |
3065 |
if (Val < 0) |
| 3066 |
Val = -Val; |
3066 |
Val = -Val; |
| 3067 |
Val = ARM_AM::getAM5Opc(AddSub, Val); |
3067 |
Val = ARM_AM::getAM5Opc(AddSub, Val); |
| 3068 |
Inst.addOperand(MCOperand::createImm(Val)); |
3068 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 3069 |
} else |
3069 |
} else |
| 3070 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
3070 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
| 3071 |
} |
3071 |
} |
| 3072 |
|
3072 |
|
| 3073 |
void addAddrMode5FP16Operands(MCInst &Inst, unsigned N) const { |
3073 |
void addAddrMode5FP16Operands(MCInst &Inst, unsigned N) const { |
| 3074 |
assert(N == 2 && "Invalid number of operands!"); |
3074 |
assert(N == 2 && "Invalid number of operands!"); |
| 3075 |
// If we have an immediate that's not a constant, treat it as a label |
3075 |
// If we have an immediate that's not a constant, treat it as a label |
| 3076 |
// reference needing a fixup. If it is a constant, it's something else |
3076 |
// reference needing a fixup. If it is a constant, it's something else |
| 3077 |
// and we reject it. |
3077 |
// and we reject it. |
| 3078 |
if (isImm()) { |
3078 |
if (isImm()) { |
| 3079 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
3079 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
| 3080 |
Inst.addOperand(MCOperand::createImm(0)); |
3080 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3081 |
return; |
3081 |
return; |
| 3082 |
} |
3082 |
} |
| 3083 |
|
3083 |
|
| 3084 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3084 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3085 |
// The lower bit is always zero and as such is not encoded. |
3085 |
// The lower bit is always zero and as such is not encoded. |
| 3086 |
if (!Memory.OffsetImm) |
3086 |
if (!Memory.OffsetImm) |
| 3087 |
Inst.addOperand(MCOperand::createImm(0)); |
3087 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3088 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
3088 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) { |
| 3089 |
int32_t Val = CE->getValue() / 2; |
3089 |
int32_t Val = CE->getValue() / 2; |
| 3090 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
3090 |
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; |
| 3091 |
// Special case for #-0 |
3091 |
// Special case for #-0 |
| 3092 |
if (Val == std::numeric_limits::min()) |
3092 |
if (Val == std::numeric_limits::min()) |
| 3093 |
Val = 0; |
3093 |
Val = 0; |
| 3094 |
if (Val < 0) |
3094 |
if (Val < 0) |
| 3095 |
Val = -Val; |
3095 |
Val = -Val; |
| 3096 |
Val = ARM_AM::getAM5FP16Opc(AddSub, Val); |
3096 |
Val = ARM_AM::getAM5FP16Opc(AddSub, Val); |
| 3097 |
Inst.addOperand(MCOperand::createImm(Val)); |
3097 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 3098 |
} else |
3098 |
} else |
| 3099 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
3099 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
| 3100 |
} |
3100 |
} |
| 3101 |
|
3101 |
|
| 3102 |
void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const { |
3102 |
void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const { |
| 3103 |
assert(N == 2 && "Invalid number of operands!"); |
3103 |
assert(N == 2 && "Invalid number of operands!"); |
| 3104 |
// If we have an immediate that's not a constant, treat it as a label |
3104 |
// If we have an immediate that's not a constant, treat it as a label |
| 3105 |
// reference needing a fixup. If it is a constant, it's something else |
3105 |
// reference needing a fixup. If it is a constant, it's something else |
| 3106 |
// and we reject it. |
3106 |
// and we reject it. |
| 3107 |
if (isImm()) { |
3107 |
if (isImm()) { |
| 3108 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
3108 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
| 3109 |
Inst.addOperand(MCOperand::createImm(0)); |
3109 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3110 |
return; |
3110 |
return; |
| 3111 |
} |
3111 |
} |
| 3112 |
|
3112 |
|
| 3113 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3113 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3114 |
addExpr(Inst, Memory.OffsetImm); |
3114 |
addExpr(Inst, Memory.OffsetImm); |
| 3115 |
} |
3115 |
} |
| 3116 |
|
3116 |
|
| 3117 |
void addMemImm7s4OffsetOperands(MCInst &Inst, unsigned N) const { |
3117 |
void addMemImm7s4OffsetOperands(MCInst &Inst, unsigned N) const { |
| 3118 |
assert(N == 2 && "Invalid number of operands!"); |
3118 |
assert(N == 2 && "Invalid number of operands!"); |
| 3119 |
// If we have an immediate that's not a constant, treat it as a label |
3119 |
// If we have an immediate that's not a constant, treat it as a label |
| 3120 |
// reference needing a fixup. If it is a constant, it's something else |
3120 |
// reference needing a fixup. If it is a constant, it's something else |
| 3121 |
// and we reject it. |
3121 |
// and we reject it. |
| 3122 |
if (isImm()) { |
3122 |
if (isImm()) { |
| 3123 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
3123 |
Inst.addOperand(MCOperand::createExpr(getImm())); |
| 3124 |
Inst.addOperand(MCOperand::createImm(0)); |
3124 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3125 |
return; |
3125 |
return; |
| 3126 |
} |
3126 |
} |
| 3127 |
|
3127 |
|
| 3128 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3128 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3129 |
addExpr(Inst, Memory.OffsetImm); |
3129 |
addExpr(Inst, Memory.OffsetImm); |
| 3130 |
} |
3130 |
} |
| 3131 |
|
3131 |
|
| 3132 |
void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const { |
3132 |
void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const { |
| 3133 |
assert(N == 2 && "Invalid number of operands!"); |
3133 |
assert(N == 2 && "Invalid number of operands!"); |
| 3134 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3134 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3135 |
if (!Memory.OffsetImm) |
3135 |
if (!Memory.OffsetImm) |
| 3136 |
Inst.addOperand(MCOperand::createImm(0)); |
3136 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3137 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
3137 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
| 3138 |
// The lower two bits are always zero and as such are not encoded. |
3138 |
// The lower two bits are always zero and as such are not encoded. |
| 3139 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); |
3139 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); |
| 3140 |
else |
3140 |
else |
| 3141 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
3141 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
| 3142 |
} |
3142 |
} |
| 3143 |
|
3143 |
|
| 3144 |
void addMemImmOffsetOperands(MCInst &Inst, unsigned N) const { |
3144 |
void addMemImmOffsetOperands(MCInst &Inst, unsigned N) const { |
| 3145 |
assert(N == 2 && "Invalid number of operands!"); |
3145 |
assert(N == 2 && "Invalid number of operands!"); |
| 3146 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3146 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3147 |
addExpr(Inst, Memory.OffsetImm); |
3147 |
addExpr(Inst, Memory.OffsetImm); |
| 3148 |
} |
3148 |
} |
| 3149 |
|
3149 |
|
| 3150 |
void addMemRegRQOffsetOperands(MCInst &Inst, unsigned N) const { |
3150 |
void addMemRegRQOffsetOperands(MCInst &Inst, unsigned N) const { |
| 3151 |
assert(N == 2 && "Invalid number of operands!"); |
3151 |
assert(N == 2 && "Invalid number of operands!"); |
| 3152 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3152 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3153 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
3153 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
| 3154 |
} |
3154 |
} |
| 3155 |
|
3155 |
|
| 3156 |
void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const { |
3156 |
void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const { |
| 3157 |
assert(N == 2 && "Invalid number of operands!"); |
3157 |
assert(N == 2 && "Invalid number of operands!"); |
| 3158 |
// If this is an immediate, it's a label reference. |
3158 |
// If this is an immediate, it's a label reference. |
| 3159 |
if (isImm()) { |
3159 |
if (isImm()) { |
| 3160 |
addExpr(Inst, getImm()); |
3160 |
addExpr(Inst, getImm()); |
| 3161 |
Inst.addOperand(MCOperand::createImm(0)); |
3161 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3162 |
return; |
3162 |
return; |
| 3163 |
} |
3163 |
} |
| 3164 |
|
3164 |
|
| 3165 |
// Otherwise, it's a normal memory reg+offset. |
3165 |
// Otherwise, it's a normal memory reg+offset. |
| 3166 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3166 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3167 |
addExpr(Inst, Memory.OffsetImm); |
3167 |
addExpr(Inst, Memory.OffsetImm); |
| 3168 |
} |
3168 |
} |
| 3169 |
|
3169 |
|
| 3170 |
void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const { |
3170 |
void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const { |
| 3171 |
assert(N == 2 && "Invalid number of operands!"); |
3171 |
assert(N == 2 && "Invalid number of operands!"); |
| 3172 |
// If this is an immediate, it's a label reference. |
3172 |
// If this is an immediate, it's a label reference. |
| 3173 |
if (isImm()) { |
3173 |
if (isImm()) { |
| 3174 |
addExpr(Inst, getImm()); |
3174 |
addExpr(Inst, getImm()); |
| 3175 |
Inst.addOperand(MCOperand::createImm(0)); |
3175 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3176 |
return; |
3176 |
return; |
| 3177 |
} |
3177 |
} |
| 3178 |
|
3178 |
|
| 3179 |
// Otherwise, it's a normal memory reg+offset. |
3179 |
// Otherwise, it's a normal memory reg+offset. |
| 3180 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3180 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3181 |
addExpr(Inst, Memory.OffsetImm); |
3181 |
addExpr(Inst, Memory.OffsetImm); |
| 3182 |
} |
3182 |
} |
| 3183 |
|
3183 |
|
| 3184 |
void addConstPoolAsmImmOperands(MCInst &Inst, unsigned N) const { |
3184 |
void addConstPoolAsmImmOperands(MCInst &Inst, unsigned N) const { |
| 3185 |
assert(N == 1 && "Invalid number of operands!"); |
3185 |
assert(N == 1 && "Invalid number of operands!"); |
| 3186 |
// This is container for the immediate that we will create the constant |
3186 |
// This is container for the immediate that we will create the constant |
| 3187 |
// pool from |
3187 |
// pool from |
| 3188 |
addExpr(Inst, getConstantPoolImm()); |
3188 |
addExpr(Inst, getConstantPoolImm()); |
| 3189 |
} |
3189 |
} |
| 3190 |
|
3190 |
|
| 3191 |
void addMemTBBOperands(MCInst &Inst, unsigned N) const { |
3191 |
void addMemTBBOperands(MCInst &Inst, unsigned N) const { |
| 3192 |
assert(N == 2 && "Invalid number of operands!"); |
3192 |
assert(N == 2 && "Invalid number of operands!"); |
| 3193 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3193 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3194 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
3194 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
| 3195 |
} |
3195 |
} |
| 3196 |
|
3196 |
|
| 3197 |
void addMemTBHOperands(MCInst &Inst, unsigned N) const { |
3197 |
void addMemTBHOperands(MCInst &Inst, unsigned N) const { |
| 3198 |
assert(N == 2 && "Invalid number of operands!"); |
3198 |
assert(N == 2 && "Invalid number of operands!"); |
| 3199 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3199 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3200 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
3200 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
| 3201 |
} |
3201 |
} |
| 3202 |
|
3202 |
|
| 3203 |
void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const { |
3203 |
void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const { |
| 3204 |
assert(N == 3 && "Invalid number of operands!"); |
3204 |
assert(N == 3 && "Invalid number of operands!"); |
| 3205 |
unsigned Val = |
3205 |
unsigned Val = |
| 3206 |
ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, |
3206 |
ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, |
| 3207 |
Memory.ShiftImm, Memory.ShiftType); |
3207 |
Memory.ShiftImm, Memory.ShiftType); |
| 3208 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3208 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3209 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
3209 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
| 3210 |
Inst.addOperand(MCOperand::createImm(Val)); |
3210 |
Inst.addOperand(MCOperand::createImm(Val)); |
| 3211 |
} |
3211 |
} |
| 3212 |
|
3212 |
|
| 3213 |
void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const { |
3213 |
void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const { |
| 3214 |
assert(N == 3 && "Invalid number of operands!"); |
3214 |
assert(N == 3 && "Invalid number of operands!"); |
| 3215 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3215 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3216 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
3216 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
| 3217 |
Inst.addOperand(MCOperand::createImm(Memory.ShiftImm)); |
3217 |
Inst.addOperand(MCOperand::createImm(Memory.ShiftImm)); |
| 3218 |
} |
3218 |
} |
| 3219 |
|
3219 |
|
| 3220 |
void addMemThumbRROperands(MCInst &Inst, unsigned N) const { |
3220 |
void addMemThumbRROperands(MCInst &Inst, unsigned N) const { |
| 3221 |
assert(N == 2 && "Invalid number of operands!"); |
3221 |
assert(N == 2 && "Invalid number of operands!"); |
| 3222 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3222 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3223 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
3223 |
Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); |
| 3224 |
} |
3224 |
} |
| 3225 |
|
3225 |
|
| 3226 |
void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const { |
3226 |
void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const { |
| 3227 |
assert(N == 2 && "Invalid number of operands!"); |
3227 |
assert(N == 2 && "Invalid number of operands!"); |
| 3228 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3228 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3229 |
if (!Memory.OffsetImm) |
3229 |
if (!Memory.OffsetImm) |
| 3230 |
Inst.addOperand(MCOperand::createImm(0)); |
3230 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3231 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
3231 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
| 3232 |
// The lower two bits are always zero and as such are not encoded. |
3232 |
// The lower two bits are always zero and as such are not encoded. |
| 3233 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); |
3233 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); |
| 3234 |
else |
3234 |
else |
| 3235 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
3235 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
| 3236 |
} |
3236 |
} |
| 3237 |
|
3237 |
|
| 3238 |
void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const { |
3238 |
void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const { |
| 3239 |
assert(N == 2 && "Invalid number of operands!"); |
3239 |
assert(N == 2 && "Invalid number of operands!"); |
| 3240 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3240 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3241 |
if (!Memory.OffsetImm) |
3241 |
if (!Memory.OffsetImm) |
| 3242 |
Inst.addOperand(MCOperand::createImm(0)); |
3242 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3243 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
3243 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
| 3244 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 2)); |
3244 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 2)); |
| 3245 |
else |
3245 |
else |
| 3246 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
3246 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
| 3247 |
} |
3247 |
} |
| 3248 |
|
3248 |
|
| 3249 |
void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const { |
3249 |
void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const { |
| 3250 |
assert(N == 2 && "Invalid number of operands!"); |
3250 |
assert(N == 2 && "Invalid number of operands!"); |
| 3251 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3251 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3252 |
addExpr(Inst, Memory.OffsetImm); |
3252 |
addExpr(Inst, Memory.OffsetImm); |
| 3253 |
} |
3253 |
} |
| 3254 |
|
3254 |
|
| 3255 |
void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const { |
3255 |
void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const { |
| 3256 |
assert(N == 2 && "Invalid number of operands!"); |
3256 |
assert(N == 2 && "Invalid number of operands!"); |
| 3257 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
3257 |
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); |
| 3258 |
if (!Memory.OffsetImm) |
3258 |
if (!Memory.OffsetImm) |
| 3259 |
Inst.addOperand(MCOperand::createImm(0)); |
3259 |
Inst.addOperand(MCOperand::createImm(0)); |
| 3260 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
3260 |
else if (const auto *CE = dyn_cast(Memory.OffsetImm)) |
| 3261 |
// The lower two bits are always zero and as such are not encoded. |
3261 |
// The lower two bits are always zero and as such are not encoded. |
| 3262 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); |
3262 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); |
| 3263 |
else |
3263 |
else |
| 3264 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
3264 |
Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); |
| 3265 |
} |
3265 |
} |
| 3266 |
|
3266 |
|
| 3267 |
void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const { |
3267 |
void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const { |
| 3268 |
assert(N == 1 && "Invalid number of operands!"); |
3268 |
assert(N == 1 && "Invalid number of operands!"); |
| 3269 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
3269 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 3270 |
assert(CE && "non-constant post-idx-imm8 operand!"); |
3270 |
assert(CE && "non-constant post-idx-imm8 operand!"); |
| 3271 |
int Imm = CE->getValue(); |
3271 |
int Imm = CE->getValue(); |
| 3272 |
bool isAdd = Imm >= 0; |
3272 |
bool isAdd = Imm >= 0; |
| 3273 |
if (Imm == std::numeric_limits::min()) Imm = 0; |
3273 |
if (Imm == std::numeric_limits::min()) Imm = 0; |
| 3274 |
Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8; |
3274 |
Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8; |
| 3275 |
Inst.addOperand(MCOperand::createImm(Imm)); |
3275 |
Inst.addOperand(MCOperand::createImm(Imm)); |
| 3276 |
} |
3276 |
} |
| 3277 |
|
3277 |
|
| 3278 |
void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const { |
3278 |
void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const { |
| 3279 |
assert(N == 1 && "Invalid number of operands!"); |
3279 |
assert(N == 1 && "Invalid number of operands!"); |
| 3280 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
3280 |
const MCConstantExpr *CE = dyn_cast(getImm()); |
| 3281 |
assert(CE && "non-constant post-idx-imm8s4 operand!"); |
3281 |
assert(CE && "non-constant post-idx-imm8s4 operand!"); |
| 3282 |
int Imm = CE->getValue(); |
3282 |
int Imm = CE->getValue(); |
| 3283 |
bool isAdd = Imm >= 0; |
3283 |
bool isAdd = Imm >= 0; |
| 3284 |
if (Imm == std::numeric_limits::min()) Imm = 0; |
3284 |
if (Imm == std::numeric_limits::min()) Imm = 0; |
| 3285 |
// Immediate is scaled by 4. |
3285 |
// Immediate is scaled by 4. |
| 3286 |
Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8; |
3286 |
Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8; |
| 3287 |
Inst.addOperand(MCOperand::createImm(Imm)); |
3287 |
Inst.addOperand(MCOperand::createImm(Imm)); |
| 3288 |
} |
3288 |
} |
| 3289 |
|
3289 |
|
| 3290 |
void addPostIdxRegOperands(MCInst &Inst, unsigned N) const { |
3290 |
void addPostIdxRegOperands(MCInst &Inst, unsigned N) const { |
| 3291 |
assert(N == 2 && "Invalid number of operands!"); |
3291 |
assert(N == 2 && "Invalid number of operands!"); |
| 3292 |
Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum)); |
3292 |
Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum)); |
| 3293 |
Inst.addOperand(MCOperand::createImm(PostIdxReg.isAdd)); |
3293 |
Inst.addOperand(MCOperand::createImm(PostIdxReg.isAdd)); |
| 3294 |
} |
3294 |
} |
| 3295 |
|
3295 |
|
| 3296 |
void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const { |
3296 |
void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const { |
| 3297 |
assert(N == 2 && "Invalid number of operands!"); |
3297 |
assert(N == 2 && "Invalid number of operands!"); |
| 3298 |
Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum)); |
3298 |
Inst.addOperand(MCOperand::createReg(PostIdxReg.RegNum)); |
| 3299 |
// The sign, shift type, and shift amount are encoded in a single operand |
3299 |
// The sign, shift type, and shift amount are encoded in a single operand |
| 3300 |
// using the AM2 encoding helpers. |
3300 |
// using the AM2 encoding helpers. |
| 3301 |
ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub; |
3301 |
ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub; |
| 3302 |
unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm, |
3302 |
unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm, |
| 3303 |
PostIdxReg.ShiftTy); |
3303 |
PostIdxReg.ShiftTy); |
| 3304 |
Inst.addOperand(MCOperand::createImm(Imm)); |
3304 |
Inst.addOperand(MCOperand::createImm(Imm)); |
| 3305 |
} |
3305 |
} |
| 3306 |
|
3306 |
|
| 3307 |
void addPowerTwoOperands(MCInst &Inst, unsigned N) const { |
3307 |
void addPowerTwoOperands(MCInst &Inst, unsigned N) const { |
| 3308 |
assert(N == 1 && "Invalid number of operands!"); |
3308 |
assert(N == 1 && "Invalid number of operands!"); |
| 3309 |
const MCConstantExpr *CE = cast(getImm()); |
3309 |
const MCConstantExpr *CE = cast(getImm()); |
| 3310 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
3310 |
Inst.addOperand(MCOperand::createImm(CE->getValue())); |
| 3311 |
} |
3311 |
} |
| 3312 |
|
3312 |
|
| 3313 |
void addMSRMaskOperands(MCInst &Inst, unsigned N) const { |
3313 |
void addMSRMaskOperands(MCInst &Inst, unsigned N) const { |
| 3314 |
assert(N == 1 && "Invalid number of operands!"); |
3314 |
assert(N == 1 && "Invalid number of operands!"); |
| 3315 |
Inst.addOperand(MCOperand::createImm(unsigned(getMSRMask()))); |
3315 |
Inst.addOperand(MCOperand::createImm(unsigned(getMSRMask()))); |
| 3316 |
} |
3316 |
} |
| 3317 |
|
3317 |
|
| 3318 |
void addBankedRegOperands(MCInst &Inst, unsigned N) const { |
3318 |
void addBankedRegOperands(MCInst &Inst, unsigned N) const { |
| 3319 |
assert(N == 1 && "Invalid number of operands!"); |
3319 |
assert(N == 1 && "Invalid number of operands!"); |
| 3320 |
Inst.addOperand(MCOperand::createImm(unsigned(getBankedReg()))); |
3320 |
Inst.addOperand(MCOperand::createImm(unsigned(getBankedReg()))); |
| 3321 |
} |
3321 |
} |
| 3322 |
|
3322 |
|
| 3323 |
void addProcIFlagsOperands(MCInst &Inst, unsigned N) const { |
3323 |
void addProcIFlagsOperands(MCInst &Inst, unsigned N) const { |
| 3324 |
assert(N == 1 && "Invalid number of operands!"); |
3324 |
assert(N == 1 && "Invalid number of operands!"); |
| 3325 |
Inst.addOperand(MCOperand::createImm(unsigned(getProcIFlags()))); |
3325 |
Inst.addOperand(MCOperand::createImm(unsigned(getProcIFlags()))); |
| 3326 |
} |
3326 |
} |
| 3327 |
|
3327 |
|
| 3328 |
void addVecListOperands(MCInst &Inst, unsigned N) const { |
3328 |
void addVecListOperands(MCInst &Inst, unsigned N) const { |
| 3329 |
assert(N == 1 && "Invalid number of operands!"); |
3329 |
assert(N == 1 && "Invalid number of operands!"); |
| 3330 |
Inst.addOperand(MCOperand::createReg(VectorList.RegNum)); |
3330 |
Inst.addOperand(MCOperand::createReg(VectorList.RegNum)); |
| 3331 |
} |
3331 |
} |
| 3332 |
|
3332 |
|
| 3333 |
void addMVEVecListOperands(MCInst &Inst, unsigned N) const { |
3333 |
void addMVEVecListOperands(MCInst &Inst, unsigned N) const { |
| 3334 |
assert(N == 1 && "Invalid number of operands!"); |
3334 |
assert(N == 1 && "Invalid number of operands!"); |
| 3335 |
|
3335 |
|
| 3336 |
// When we come here, the VectorList field will identify a range |
3336 |
// When we come here, the VectorList field will identify a range |
| 3337 |
// of q-registers by its base register and length, and it will |
3337 |
// of q-registers by its base register and length, and it will |
| 3338 |
// have already been error-checked to be the expected length of |
3338 |
// have already been error-checked to be the expected length of |
| 3339 |
// range and contain only q-regs in the range q0-q7. So we can |
3339 |
// range and contain only q-regs in the range q0-q7. So we can |
| 3340 |
// count on the base register being in the range q0-q6 (for 2 |
3340 |
// count on the base register being in the range q0-q6 (for 2 |
| 3341 |
// regs) or q0-q4 (for 4) |
3341 |
// regs) or q0-q4 (for 4) |
| 3342 |
// |
3342 |
// |
| 3343 |
// The MVE instructions taking a register range of this kind will |
3343 |
// The MVE instructions taking a register range of this kind will |
| 3344 |
// need an operand in the MQQPR or MQQQQPR class, representing the |
3344 |
// need an operand in the MQQPR or MQQQQPR class, representing the |
| 3345 |
// entire range as a unit. So we must translate into that class, |
3345 |
// entire range as a unit. So we must translate into that class, |
| 3346 |
// by finding the index of the base register in the MQPR reg |
3346 |
// by finding the index of the base register in the MQPR reg |
| 3347 |
// class, and returning the super-register at the corresponding |
3347 |
// class, and returning the super-register at the corresponding |
| 3348 |
// index in the target class. |
3348 |
// index in the target class. |
| 3349 |
|
3349 |
|
| 3350 |
const MCRegisterClass *RC_in = &ARMMCRegisterClasses[ARM::MQPRRegClassID]; |
3350 |
const MCRegisterClass *RC_in = &ARMMCRegisterClasses[ARM::MQPRRegClassID]; |
| 3351 |
const MCRegisterClass *RC_out = |
3351 |
const MCRegisterClass *RC_out = |
| 3352 |
(VectorList.Count == 2) ? &ARMMCRegisterClasses[ARM::MQQPRRegClassID] |
3352 |
(VectorList.Count == 2) ? &ARMMCRegisterClasses[ARM::MQQPRRegClassID] |
| 3353 |
: &ARMMCRegisterClasses[ARM::MQQQQPRRegClassID]; |
3353 |
: &ARMMCRegisterClasses[ARM::MQQQQPRRegClassID]; |
| 3354 |
|
3354 |
|
| 3355 |
unsigned I, E = RC_out->getNumRegs(); |
3355 |
unsigned I, E = RC_out->getNumRegs(); |
| 3356 |
for (I = 0; I < E; I++) |
3356 |
for (I = 0; I < E; I++) |
| 3357 |
if (RC_in->getRegister(I) == VectorList.RegNum) |
3357 |
if (RC_in->getRegister(I) == VectorList.RegNum) |
| 3358 |
break; |
3358 |
break; |
| 3359 |
assert(I < E && "Invalid vector list start register!"); |
3359 |
assert(I < E && "Invalid vector list start register!"); |
| 3360 |
|
3360 |
|
| 3361 |
Inst.addOperand(MCOperand::createReg(RC_out->getRegister(I))); |
3361 |
Inst.addOperand(MCOperand::createReg(RC_out->getRegister(I))); |
| 3362 |
} |
3362 |
} |
| 3363 |
|
3363 |
|
| 3364 |
void addVecListIndexedOperands(MCInst &Inst, unsigned N) const { |
3364 |
void addVecListIndexedOperands(MCInst &Inst, unsigned N) const { |
| 3365 |
assert(N == 2 && "Invalid number of operands!"); |
3365 |
assert(N == 2 && "Invalid number of operands!"); |
| 3366 |
Inst.addOperand(MCOperand::createReg(VectorList.RegNum)); |
3366 |
Inst.addOperand(MCOperand::createReg(VectorList.RegNum)); |
| 3367 |
Inst.addOperand(MCOperand::createImm(VectorList.LaneIndex)); |
3367 |
Inst.addOperand(MCOperand::createImm(VectorList.LaneIndex)); |
| 3368 |
} |
3368 |
} |
| 3369 |
|
3369 |
|
| 3370 |
void addVectorIndex8Operands(MCInst &Inst, unsigned N) const { |
3370 |
void addVectorIndex8Operands(MCInst &Inst, unsigned N) const { |
| 3371 |
assert(N == 1 && "Invalid number of operands!"); |
3371 |
assert(N == 1 && "Invalid number of operands!"); |
| 3372 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
3372 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
| 3373 |
} |
3373 |
} |
| 3374 |
|
3374 |
|
| 3375 |
void addVectorIndex16Operands(MCInst &Inst, unsigned N) const { |
3375 |
void addVectorIndex16Operands(MCInst &Inst, unsigned N) const { |
| 3376 |
assert(N == 1 && "Invalid number of operands!"); |
3376 |
assert(N == 1 && "Invalid number of operands!"); |
| 3377 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
3377 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
| 3378 |
} |
3378 |
} |
| 3379 |
|
3379 |
|
| 3380 |
void addVectorIndex32Operands(MCInst &Inst, unsigned N) const { |
3380 |
void addVectorIndex32Operands(MCInst &Inst, unsigned N) const { |
| 3381 |
assert(N == 1 && "Invalid number of operands!"); |
3381 |
assert(N == 1 && "Invalid number of operands!"); |
| 3382 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
3382 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
| 3383 |
} |
3383 |
} |
| 3384 |
|
3384 |
|
| 3385 |
void addVectorIndex64Operands(MCInst &Inst, unsigned N) const { |
3385 |
void addVectorIndex64Operands(MCInst &Inst, unsigned N) const { |
| 3386 |
assert(N == 1 && "Invalid number of operands!"); |
3386 |
assert(N == 1 && "Invalid number of operands!"); |
| 3387 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
3387 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
| 3388 |
} |
3388 |
} |
| 3389 |
|
3389 |
|
| 3390 |
void addMVEVectorIndexOperands(MCInst &Inst, unsigned N) const { |
3390 |
void addMVEVectorIndexOperands(MCInst &Inst, unsigned N) const { |
| 3391 |
assert(N == 1 && "Invalid number of operands!"); |
3391 |
assert(N == 1 && "Invalid number of operands!"); |
| 3392 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
3392 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
| 3393 |
} |
3393 |
} |
| 3394 |
|
3394 |
|
| 3395 |
void addMVEPairVectorIndexOperands(MCInst &Inst, unsigned N) const { |
3395 |
void addMVEPairVectorIndexOperands(MCInst &Inst, unsigned N) const { |
| 3396 |
assert(N == 1 && "Invalid number of operands!"); |
3396 |
assert(N == 1 && "Invalid number of operands!"); |
| 3397 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
3397 |
Inst.addOperand(MCOperand::createImm(getVectorIndex())); |
| 3398 |
} |
3398 |
} |
| 3399 |
|
3399 |
|
| 3400 |
void addNEONi8splatOperands(MCInst &Inst, unsigned N) const { |
3400 |
void addNEONi8splatOperands(MCInst &Inst, unsigned N) const { |
| 3401 |
assert(N == 1 && "Invalid number of operands!"); |
3401 |
assert(N == 1 && "Invalid number of operands!"); |
| 3402 |
// The immediate encodes the type of constant as well as the value. |
3402 |
// The immediate encodes the type of constant as well as the value. |
| 3403 |
// Mask in that this is an i8 splat. |
3403 |
// Mask in that this is an i8 splat. |
| 3404 |
const MCConstantExpr *CE = cast(getImm()); |
3404 |
const MCConstantExpr *CE = cast(getImm()); |
| 3405 |
Inst.addOperand(MCOperand::createImm(CE->getValue() | 0xe00)); |
3405 |
Inst.addOperand(MCOperand::createImm(CE->getValue() | 0xe00)); |
| 3406 |
} |
3406 |
} |
| 3407 |
|
3407 |
|
| 3408 |
void addNEONi16splatOperands(MCInst &Inst, unsigned N) const { |
3408 |
void addNEONi16splatOperands(MCInst &Inst, unsigned N) const { |
| 3409 |
assert(N == 1 && "Invalid number of operands!"); |
3409 |
assert(N == 1 && "Invalid number of operands!"); |
| 3410 |
// The immediate encodes the type of constant as well as the value. |
3410 |
// The immediate encodes the type of constant as well as the value. |
| 3411 |
const MCConstantExpr *CE = cast(getImm()); |
3411 |
const MCConstantExpr *CE = cast(getImm()); |
| 3412 |
unsigned Value = CE->getValue(); |
3412 |
unsigned Value = CE->getValue(); |
| 3413 |
Value = ARM_AM::encodeNEONi16splat(Value); |
3413 |
Value = ARM_AM::encodeNEONi16splat(Value); |
| 3414 |
Inst.addOperand(MCOperand::createImm(Value)); |
3414 |
Inst.addOperand(MCOperand::createImm(Value)); |
| 3415 |
} |
3415 |
} |
| 3416 |
|
3416 |
|
| 3417 |
void addNEONi16splatNotOperands(MCInst &Inst, unsigned N) const { |
3417 |
void addNEONi16splatNotOperands(MCInst &Inst, unsigned N) const { |
| 3418 |
assert(N == 1 && "Invalid number of operands!"); |
3418 |
assert(N == 1 && "Invalid number of operands!"); |
| 3419 |
// The immediate encodes the type of constant as well as the value. |
3419 |
// The immediate encodes the type of constant as well as the value. |
| 3420 |
const MCConstantExpr *CE = cast(getImm()); |
3420 |
const MCConstantExpr *CE = cast(getImm()); |
| 3421 |
unsigned Value = CE->getValue(); |
3421 |
unsigned Value = CE->getValue(); |
| 3422 |
Value = ARM_AM::encodeNEONi16splat(~Value & 0xffff); |
3422 |
Value = ARM_AM::encodeNEONi16splat(~Value & 0xffff); |
| 3423 |
Inst.addOperand(MCOperand::createImm(Value)); |
3423 |
Inst.addOperand(MCOperand::createImm(Value)); |
| 3424 |
} |
3424 |
} |
| 3425 |
|
3425 |
|
| 3426 |
void addNEONi32splatOperands(MCInst &Inst, unsigned N) const { |
3426 |
void addNEONi32splatOperands(MCInst &Inst, unsigned N) const { |
| 3427 |
assert(N == 1 && "Invalid number of operands!"); |
3427 |
assert(N == 1 && "Invalid number of operands!"); |
| 3428 |
// The immediate encodes the type of constant as well as the value. |
3428 |
// The immediate encodes the type of constant as well as the value. |
| 3429 |
const MCConstantExpr *CE = cast(getImm()); |
3429 |
const MCConstantExpr *CE = cast(getImm()); |
| 3430 |
unsigned Value = CE->getValue(); |
3430 |
unsigned Value = CE->getValue(); |
| 3431 |
Value = ARM_AM::encodeNEONi32splat(Value); |
3431 |
Value = ARM_AM::encodeNEONi32splat(Value); |
| 3432 |
Inst.addOperand(MCOperand::createImm(Value)); |
3432 |
Inst.addOperand(MCOperand::createImm(Value)); |
| 3433 |
} |
3433 |
} |
| 3434 |
|
3434 |
|
| 3435 |
void addNEONi32splatNotOperands(MCInst &Inst, unsigned N) const { |
3435 |
void addNEONi32splatNotOperands(MCInst &Inst, unsigned N) const { |
| 3436 |
assert(N == 1 && "Invalid number of operands!"); |
3436 |
assert(N == 1 && "Invalid number of operands!"); |
| 3437 |
// The immediate encodes the type of constant as well as the value. |
3437 |
// The immediate encodes the type of constant as well as the value. |
| 3438 |
const MCConstantExpr *CE = cast(getImm()); |
3438 |
const MCConstantExpr *CE = cast(getImm()); |
| 3439 |
unsigned Value = CE->getValue(); |
3439 |
unsigned Value = CE->getValue(); |
| 3440 |
Value = ARM_AM::encodeNEONi32splat(~Value); |
3440 |
Value = ARM_AM::encodeNEONi32splat(~Value); |
| 3441 |
Inst.addOperand(MCOperand::createImm(Value)); |
3441 |
Inst.addOperand(MCOperand::createImm(Value)); |
| 3442 |
} |
3442 |
} |
| 3443 |
|
3443 |
|
| 3444 |
void addNEONi8ReplicateOperands(MCInst &Inst, bool Inv) const { |
3444 |
void addNEONi8ReplicateOperands(MCInst &Inst, bool Inv) const { |
| 3445 |
// The immediate encodes the type of constant as well as the value. |
3445 |
// The immediate encodes the type of constant as well as the value. |
| 3446 |
const MCConstantExpr *CE = cast(getImm()); |
3446 |
const MCConstantExpr *CE = cast(getImm()); |
| 3447 |
assert((Inst.getOpcode() == ARM::VMOVv8i8 || |
3447 |
assert((Inst.getOpcode() == ARM::VMOVv8i8 || |
| 3448 |
Inst.getOpcode() == ARM::VMOVv16i8) && |
3448 |
Inst.getOpcode() == ARM::VMOVv16i8) && |
| 3449 |
"All instructions that wants to replicate non-zero byte " |
3449 |
"All instructions that wants to replicate non-zero byte " |
| 3450 |
"always must be replaced with VMOVv8i8 or VMOVv16i8."); |
3450 |
"always must be replaced with VMOVv8i8 or VMOVv16i8."); |
| 3451 |
unsigned Value = CE->getValue(); |
3451 |
unsigned Value = CE->getValue(); |
| 3452 |
if (Inv) |
3452 |
if (Inv) |
| 3453 |
Value = ~Value; |
3453 |
Value = ~Value; |
| 3454 |
unsigned B = Value & 0xff; |
3454 |
unsigned B = Value & 0xff; |
| 3455 |
B |= 0xe00; // cmode = 0b1110 |
3455 |
B |= 0xe00; // cmode = 0b1110 |
| 3456 |
Inst.addOperand(MCOperand::createImm(B)); |
3456 |
Inst.addOperand(MCOperand::createImm(B)); |
| 3457 |
} |
3457 |
} |
| 3458 |
|
3458 |
|
| 3459 |
void addNEONinvi8ReplicateOperands(MCInst &Inst, unsigned N) const { |
3459 |
void addNEONinvi8ReplicateOperands(MCInst &Inst, unsigned N) const { |
| 3460 |
assert(N == 1 && "Invalid number of operands!"); |
3460 |
assert(N == 1 && "Invalid number of operands!"); |
| 3461 |
addNEONi8ReplicateOperands(Inst, true); |
3461 |
addNEONi8ReplicateOperands(Inst, true); |
| 3462 |
} |
3462 |
} |
| 3463 |
|
3463 |
|
| 3464 |
static unsigned encodeNeonVMOVImmediate(unsigned Value) { |
3464 |
static unsigned encodeNeonVMOVImmediate(unsigned Value) { |
| 3465 |
if (Value >= 256 && Value <= 0xffff) |
3465 |
if (Value >= 256 && Value <= 0xffff) |
| 3466 |
Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200); |
3466 |
Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200); |
| 3467 |
else if (Value > 0xffff && Value <= 0xffffff) |
3467 |
else if (Value > 0xffff && Value <= 0xffffff) |
| 3468 |
Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400); |
3468 |
Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400); |
| 3469 |
else if (Value > 0xffffff) |
3469 |
else if (Value > 0xffffff) |
| 3470 |
Value = (Value >> 24) | 0x600; |
3470 |
Value = (Value >> 24) | 0x600; |
| 3471 |
return Value; |
3471 |
return Value; |
| 3472 |
} |
3472 |
} |
| 3473 |
|
3473 |
|
| 3474 |
void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const { |
3474 |
void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const { |
| 3475 |
assert(N == 1 && "Invalid number of operands!"); |
3475 |
assert(N == 1 && "Invalid number of operands!"); |
| 3476 |
// The immediate encodes the type of constant as well as the value. |
3476 |
// The immediate encodes the type of constant as well as the value. |
| 3477 |
const MCConstantExpr *CE = cast(getImm()); |
3477 |
const MCConstantExpr *CE = cast(getImm()); |
| 3478 |
unsigned Value = encodeNeonVMOVImmediate(CE->getValue()); |
3478 |
unsigned Value = encodeNeonVMOVImmediate(CE->getValue()); |
| 3479 |
Inst.addOperand(MCOperand::createImm(Value)); |
3479 |
Inst.addOperand(MCOperand::createImm(Value)); |
| 3480 |
} |
3480 |
} |
| 3481 |
|
3481 |
|
| 3482 |
void addNEONvmovi8ReplicateOperands(MCInst &Inst, unsigned N) const { |
3482 |
void addNEONvmovi8ReplicateOperands(MCInst &Inst, unsigned N) const { |
| 3483 |
assert(N == 1 && "Invalid number of operands!"); |
3483 |
assert(N == 1 && "Invalid number of operands!"); |
| 3484 |
addNEONi8ReplicateOperands(Inst, false); |
3484 |
addNEONi8ReplicateOperands(Inst, false); |
| 3485 |
} |
3485 |
} |
| 3486 |
|
3486 |
|
| 3487 |
void addNEONvmovi16ReplicateOperands(MCInst &Inst, unsigned N) const { |
3487 |
void addNEONvmovi16ReplicateOperands(MCInst &Inst, unsigned N) const { |
| 3488 |
assert(N == 1 && "Invalid number of operands!"); |
3488 |
assert(N == 1 && "Invalid number of operands!"); |
| 3489 |
const MCConstantExpr *CE = cast(getImm()); |
3489 |
const MCConstantExpr *CE = cast(getImm()); |
| 3490 |
assert((Inst.getOpcode() == ARM::VMOVv4i16 || |
3490 |
assert((Inst.getOpcode() == ARM::VMOVv4i16 || |
| 3491 |
Inst.getOpcode() == ARM::VMOVv8i16 || |
3491 |
Inst.getOpcode() == ARM::VMOVv8i16 || |
| 3492 |
Inst.getOpcode() == ARM::VMVNv4i16 || |
3492 |
Inst.getOpcode() == ARM::VMVNv4i16 || |
| 3493 |
Inst.getOpcode() == ARM::VMVNv8i16) && |
3493 |
Inst.getOpcode() == ARM::VMVNv8i16) && |
| 3494 |
"All instructions that want to replicate non-zero half-word " |
3494 |
"All instructions that want to replicate non-zero half-word " |
| 3495 |
"always must be replaced with V{MOV,MVN}v{4,8}i16."); |
3495 |
"always must be replaced with V{MOV,MVN}v{4,8}i16."); |
| 3496 |
uint64_t Value = CE->getValue(); |
3496 |
uint64_t Value = CE->getValue(); |
| 3497 |
unsigned Elem = Value & 0xffff; |
3497 |
unsigned Elem = Value & 0xffff; |
| 3498 |
if (Elem >= 256) |
3498 |
if (Elem >= 256) |
| 3499 |
Elem = (Elem >> 8) | 0x200; |
3499 |
Elem = (Elem >> 8) | 0x200; |
| 3500 |
Inst.addOperand(MCOperand::createImm(Elem)); |
3500 |
Inst.addOperand(MCOperand::createImm(Elem)); |
| 3501 |
} |
3501 |
} |
| 3502 |
|
3502 |
|
| 3503 |
void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const { |
3503 |
void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const { |
| 3504 |
assert(N == 1 && "Invalid number of operands!"); |
3504 |
assert(N == 1 && "Invalid number of operands!"); |
| 3505 |
// The immediate encodes the type of constant as well as the value. |
3505 |
// The immediate encodes the type of constant as well as the value. |
| 3506 |
const MCConstantExpr *CE = cast(getImm()); |
3506 |
const MCConstantExpr *CE = cast(getImm()); |
| 3507 |
unsigned Value = encodeNeonVMOVImmediate(~CE->getValue()); |
3507 |
unsigned Value = encodeNeonVMOVImmediate(~CE->getValue()); |
| 3508 |
Inst.addOperand(MCOperand::createImm(Value)); |
3508 |
Inst.addOperand(MCOperand::createImm(Value)); |
| 3509 |
} |
3509 |
} |
| 3510 |
|
3510 |
|
| 3511 |
void addNEONvmovi32ReplicateOperands(MCInst &Inst, unsigned N) const { |
3511 |
void addNEONvmovi32ReplicateOperands(MCInst &Inst, unsigned N) const { |
| 3512 |
assert(N == 1 && "Invalid number of operands!"); |
3512 |
assert(N == 1 && "Invalid number of operands!"); |
| 3513 |
const MCConstantExpr *CE = cast(getImm()); |
3513 |
const MCConstantExpr *CE = cast(getImm()); |
| 3514 |
assert((Inst.getOpcode() == ARM::VMOVv2i32 || |
3514 |
assert((Inst.getOpcode() == ARM::VMOVv2i32 || |
| 3515 |
Inst.getOpcode() == ARM::VMOVv4i32 || |
3515 |
Inst.getOpcode() == ARM::VMOVv4i32 || |
| 3516 |
Inst.getOpcode() == ARM::VMVNv2i32 || |
3516 |
Inst.getOpcode() == ARM::VMVNv2i32 || |
| 3517 |
Inst.getOpcode() == ARM::VMVNv4i32) && |
3517 |
Inst.getOpcode() == ARM::VMVNv4i32) && |
| 3518 |
"All instructions that want to replicate non-zero word " |
3518 |
"All instructions that want to replicate non-zero word " |
| 3519 |
"always must be replaced with V{MOV,MVN}v{2,4}i32."); |
3519 |
"always must be replaced with V{MOV,MVN}v{2,4}i32."); |
| 3520 |
uint64_t Value = CE->getValue(); |
3520 |
uint64_t Value = CE->getValue(); |
| 3521 |
unsigned Elem = encodeNeonVMOVImmediate(Value & 0xffffffff); |
3521 |
unsigned Elem = encodeNeonVMOVImmediate(Value & 0xffffffff); |
| 3522 |
Inst.addOperand(MCOperand::createImm(Elem)); |
3522 |
Inst.addOperand(MCOperand::createImm(Elem)); |
| 3523 |
} |
3523 |
} |
| 3524 |
|
3524 |
|
| 3525 |
void addNEONi64splatOperands(MCInst &Inst, unsigned N) const { |
3525 |
void addNEONi64splatOperands(MCInst &Inst, unsigned N) const { |
| 3526 |
assert(N == 1 && "Invalid number of operands!"); |
3526 |
assert(N == 1 && "Invalid number of operands!"); |
| 3527 |
// The immediate encodes the type of constant as well as the value. |
3527 |
// The immediate encodes the type of constant as well as the value. |
| 3528 |
const MCConstantExpr *CE = cast(getImm()); |
3528 |
const MCConstantExpr *CE = cast(getImm()); |
| 3529 |
uint64_t Value = CE->getValue(); |
3529 |
uint64_t Value = CE->getValue(); |
| 3530 |
unsigned Imm = 0; |
3530 |
unsigned Imm = 0; |
| 3531 |
for (unsigned i = 0; i < 8; ++i, Value >>= 8) { |
3531 |
for (unsigned i = 0; i < 8; ++i, Value >>= 8) { |
| 3532 |
Imm |= (Value & 1) << i; |
3532 |
Imm |= (Value & 1) << i; |
| 3533 |
} |
3533 |
} |
| 3534 |
Inst.addOperand(MCOperand::createImm(Imm | 0x1e00)); |
3534 |
Inst.addOperand(MCOperand::createImm(Imm | 0x1e00)); |
| 3535 |
} |
3535 |
} |
| 3536 |
|
3536 |
|
| 3537 |
void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const { |
3537 |
void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const { |
| 3538 |
assert(N == 1 && "Invalid number of operands!"); |
3538 |
assert(N == 1 && "Invalid number of operands!"); |
| 3539 |
const MCConstantExpr *CE = cast(getImm()); |
3539 |
const MCConstantExpr *CE = cast(getImm()); |
| 3540 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 90)); |
3540 |
Inst.addOperand(MCOperand::createImm(CE->getValue() / 90)); |
| 3541 |
} |
3541 |
} |
| 3542 |
|
3542 |
|
| 3543 |
void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const { |
3543 |
void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const { |
| 3544 |
assert(N == 1 && "Invalid number of operands!"); |
3544 |
assert(N == 1 && "Invalid number of operands!"); |
| 3545 |
const MCConstantExpr *CE = cast(getImm()); |
3545 |
const MCConstantExpr *CE = cast(getImm()); |
| 3546 |
Inst.addOperand(MCOperand::createImm((CE->getValue() - 90) / 180)); |
3546 |
Inst.addOperand(MCOperand::createImm((CE->getValue() - 90) / 180)); |
| 3547 |
} |
3547 |
} |
| 3548 |
|
3548 |
|
| 3549 |
void addMveSaturateOperands(MCInst &Inst, unsigned N) const { |
3549 |
void addMveSaturateOperands(MCInst &Inst, unsigned N) const { |
| 3550 |
assert(N == 1 && "Invalid number of operands!"); |
3550 |
assert(N == 1 && "Invalid number of operands!"); |
| 3551 |
const MCConstantExpr *CE = cast(getImm()); |
3551 |
const MCConstantExpr *CE = cast(getImm()); |
| 3552 |
unsigned Imm = CE->getValue(); |
3552 |
unsigned Imm = CE->getValue(); |
| 3553 |
assert((Imm == 48 || Imm == 64) && "Invalid saturate operand"); |
3553 |
assert((Imm == 48 || Imm == 64) && "Invalid saturate operand"); |
| 3554 |
Inst.addOperand(MCOperand::createImm(Imm == 48 ? 1 : 0)); |
3554 |
Inst.addOperand(MCOperand::createImm(Imm == 48 ? 1 : 0)); |
| 3555 |
} |
3555 |
} |
| 3556 |
|
3556 |
|
| 3557 |
void print(raw_ostream &OS) const override; |
3557 |
void print(raw_ostream &OS) const override; |
| 3558 |
|
3558 |
|
| 3559 |
static std::unique_ptr CreateITMask(unsigned Mask, SMLoc S) { |
3559 |
static std::unique_ptr CreateITMask(unsigned Mask, SMLoc S) { |
| 3560 |
auto Op = std::make_unique(k_ITCondMask); |
3560 |
auto Op = std::make_unique(k_ITCondMask); |
| 3561 |
Op->ITMask.Mask = Mask; |
3561 |
Op->ITMask.Mask = Mask; |
| 3562 |
Op->StartLoc = S; |
3562 |
Op->StartLoc = S; |
| 3563 |
Op->EndLoc = S; |
3563 |
Op->EndLoc = S; |
| 3564 |
return Op; |
3564 |
return Op; |
| 3565 |
} |
3565 |
} |
| 3566 |
|
3566 |
|
| 3567 |
static std::unique_ptr CreateCondCode(ARMCC::CondCodes CC, |
3567 |
static std::unique_ptr CreateCondCode(ARMCC::CondCodes CC, |
| 3568 |
SMLoc S) { |
3568 |
SMLoc S) { |
| 3569 |
auto Op = std::make_unique(k_CondCode); |
3569 |
auto Op = std::make_unique(k_CondCode); |
| 3570 |
Op->CC.Val = CC; |
3570 |
Op->CC.Val = CC; |
| 3571 |
Op->StartLoc = S; |
3571 |
Op->StartLoc = S; |
| 3572 |
Op->EndLoc = S; |
3572 |
Op->EndLoc = S; |
| 3573 |
return Op; |
3573 |
return Op; |
| 3574 |
} |
3574 |
} |
| 3575 |
|
3575 |
|
| 3576 |
static std::unique_ptr CreateVPTPred(ARMVCC::VPTCodes CC, |
3576 |
static std::unique_ptr CreateVPTPred(ARMVCC::VPTCodes CC, |
| 3577 |
SMLoc S) { |
3577 |
SMLoc S) { |
| 3578 |
auto Op = std::make_unique(k_VPTPred); |
3578 |
auto Op = std::make_unique(k_VPTPred); |
| 3579 |
Op->VCC.Val = CC; |
3579 |
Op->VCC.Val = CC; |
| 3580 |
Op->StartLoc = S; |
3580 |
Op->StartLoc = S; |
| 3581 |
Op->EndLoc = S; |
3581 |
Op->EndLoc = S; |
| 3582 |
return Op; |
3582 |
return Op; |
| 3583 |
} |
3583 |
} |
| 3584 |
|
3584 |
|
| 3585 |
static std::unique_ptr CreateCoprocNum(unsigned CopVal, SMLoc S) { |
3585 |
static std::unique_ptr CreateCoprocNum(unsigned CopVal, SMLoc S) { |
| 3586 |
auto Op = std::make_unique(k_CoprocNum); |
3586 |
auto Op = std::make_unique(k_CoprocNum); |
| 3587 |
Op->Cop.Val = CopVal; |
3587 |
Op->Cop.Val = CopVal; |
| 3588 |
Op->StartLoc = S; |
3588 |
Op->StartLoc = S; |
| 3589 |
Op->EndLoc = S; |
3589 |
Op->EndLoc = S; |
| 3590 |
return Op; |
3590 |
return Op; |
| 3591 |
} |
3591 |
} |
| 3592 |
|
3592 |
|
| 3593 |
static std::unique_ptr CreateCoprocReg(unsigned CopVal, SMLoc S) { |
3593 |
static std::unique_ptr CreateCoprocReg(unsigned CopVal, SMLoc S) { |
| 3594 |
auto Op = std::make_unique(k_CoprocReg); |
3594 |
auto Op = std::make_unique(k_CoprocReg); |
| 3595 |
Op->Cop.Val = CopVal; |
3595 |
Op->Cop.Val = CopVal; |
| 3596 |
Op->StartLoc = S; |
3596 |
Op->StartLoc = S; |
| 3597 |
Op->EndLoc = S; |
3597 |
Op->EndLoc = S; |
| 3598 |
return Op; |
3598 |
return Op; |
| 3599 |
} |
3599 |
} |
| 3600 |
|
3600 |
|
| 3601 |
static std::unique_ptr CreateCoprocOption(unsigned Val, SMLoc S, |
3601 |
static std::unique_ptr CreateCoprocOption(unsigned Val, SMLoc S, |
| 3602 |
SMLoc E) { |
3602 |
SMLoc E) { |
| 3603 |
auto Op = std::make_unique(k_CoprocOption); |
3603 |
auto Op = std::make_unique(k_CoprocOption); |
| 3604 |
Op->Cop.Val = Val; |
3604 |
Op->Cop.Val = Val; |
| 3605 |
Op->StartLoc = S; |
3605 |
Op->StartLoc = S; |
| 3606 |
Op->EndLoc = E; |
3606 |
Op->EndLoc = E; |
| 3607 |
return Op; |
3607 |
return Op; |
| 3608 |
} |
3608 |
} |
| 3609 |
|
3609 |
|
| 3610 |
static std::unique_ptr CreateCCOut(unsigned RegNum, SMLoc S) { |
3610 |
static std::unique_ptr CreateCCOut(unsigned RegNum, SMLoc S) { |
| 3611 |
auto Op = std::make_unique(k_CCOut); |
3611 |
auto Op = std::make_unique(k_CCOut); |
| 3612 |
Op->Reg.RegNum = RegNum; |
3612 |
Op->Reg.RegNum = RegNum; |
| 3613 |
Op->StartLoc = S; |
3613 |
Op->StartLoc = S; |
| 3614 |
Op->EndLoc = S; |
3614 |
Op->EndLoc = S; |
| 3615 |
return Op; |
3615 |
return Op; |
| 3616 |
} |
3616 |
} |
| 3617 |
|
3617 |
|
| 3618 |
static std::unique_ptr CreateToken(StringRef Str, SMLoc S) { |
3618 |
static std::unique_ptr CreateToken(StringRef Str, SMLoc S) { |
| 3619 |
auto Op = std::make_unique(k_Token); |
3619 |
auto Op = std::make_unique(k_Token); |
| 3620 |
Op->Tok.Data = Str.data(); |
3620 |
Op->Tok.Data = Str.data(); |
| 3621 |
Op->Tok.Length = Str.size(); |
3621 |
Op->Tok.Length = Str.size(); |
| 3622 |
Op->StartLoc = S; |
3622 |
Op->StartLoc = S; |
| 3623 |
Op->EndLoc = S; |
3623 |
Op->EndLoc = S; |
| 3624 |
return Op; |
3624 |
return Op; |
| 3625 |
} |
3625 |
} |
| 3626 |
|
3626 |
|
| 3627 |
static std::unique_ptr CreateReg(unsigned RegNum, SMLoc S, |
3627 |
static std::unique_ptr CreateReg(unsigned RegNum, SMLoc S, |
| 3628 |
SMLoc E) { |
3628 |
SMLoc E) { |
| 3629 |
auto Op = std::make_unique(k_Register); |
3629 |
auto Op = std::make_unique(k_Register); |
| 3630 |
Op->Reg.RegNum = RegNum; |
3630 |
Op->Reg.RegNum = RegNum; |
| 3631 |
Op->StartLoc = S; |
3631 |
Op->StartLoc = S; |
| 3632 |
Op->EndLoc = E; |
3632 |
Op->EndLoc = E; |
| 3633 |
return Op; |
3633 |
return Op; |
| 3634 |
} |
3634 |
} |
| 3635 |
|
3635 |
|
| 3636 |
static std::unique_ptr |
3636 |
static std::unique_ptr |
| 3637 |
CreateShiftedRegister(ARM_AM::ShiftOpc ShTy, unsigned SrcReg, |
3637 |
CreateShiftedRegister(ARM_AM::ShiftOpc ShTy, unsigned SrcReg, |
| 3638 |
unsigned ShiftReg, unsigned ShiftImm, SMLoc S, |
3638 |
unsigned ShiftReg, unsigned ShiftImm, SMLoc S, |
| 3639 |
SMLoc E) { |
3639 |
SMLoc E) { |
| 3640 |
auto Op = std::make_unique(k_ShiftedRegister); |
3640 |
auto Op = std::make_unique(k_ShiftedRegister); |
| 3641 |
Op->RegShiftedReg.ShiftTy = ShTy; |
3641 |
Op->RegShiftedReg.ShiftTy = ShTy; |
| 3642 |
Op->RegShiftedReg.SrcReg = SrcReg; |
3642 |
Op->RegShiftedReg.SrcReg = SrcReg; |
| 3643 |
Op->RegShiftedReg.ShiftReg = ShiftReg; |
3643 |
Op->RegShiftedReg.ShiftReg = ShiftReg; |
| 3644 |
Op->RegShiftedReg.ShiftImm = ShiftImm; |
3644 |
Op->RegShiftedReg.ShiftImm = ShiftImm; |
| 3645 |
Op->StartLoc = S; |
3645 |
Op->StartLoc = S; |
| 3646 |
Op->EndLoc = E; |
3646 |
Op->EndLoc = E; |
| 3647 |
return Op; |
3647 |
return Op; |
| 3648 |
} |
3648 |
} |
| 3649 |
|
3649 |
|
| 3650 |
static std::unique_ptr |
3650 |
static std::unique_ptr |
| 3651 |
CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy, unsigned SrcReg, |
3651 |
CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy, unsigned SrcReg, |
| 3652 |
unsigned ShiftImm, SMLoc S, SMLoc E) { |
3652 |
unsigned ShiftImm, SMLoc S, SMLoc E) { |
| 3653 |
auto Op = std::make_unique(k_ShiftedImmediate); |
3653 |
auto Op = std::make_unique(k_ShiftedImmediate); |
| 3654 |
Op->RegShiftedImm.ShiftTy = ShTy; |
3654 |
Op->RegShiftedImm.ShiftTy = ShTy; |
| 3655 |
Op->RegShiftedImm.SrcReg = SrcReg; |
3655 |
Op->RegShiftedImm.SrcReg = SrcReg; |
| 3656 |
Op->RegShiftedImm.ShiftImm = ShiftImm; |
3656 |
Op->RegShiftedImm.ShiftImm = ShiftImm; |
| 3657 |
Op->StartLoc = S; |
3657 |
Op->StartLoc = S; |
| 3658 |
Op->EndLoc = E; |
3658 |
Op->EndLoc = E; |
| 3659 |
return Op; |
3659 |
return Op; |
| 3660 |
} |
3660 |
} |
| 3661 |
|
3661 |
|
| 3662 |
static std::unique_ptr CreateShifterImm(bool isASR, unsigned Imm, |
3662 |
static std::unique_ptr CreateShifterImm(bool isASR, unsigned Imm, |
| 3663 |
SMLoc S, SMLoc E) { |
3663 |
SMLoc S, SMLoc E) { |
| 3664 |
auto Op = std::make_unique(k_ShifterImmediate); |
3664 |
auto Op = std::make_unique(k_ShifterImmediate); |
| 3665 |
Op->ShifterImm.isASR = isASR; |
3665 |
Op->ShifterImm.isASR = isASR; |
| 3666 |
Op->ShifterImm.Imm = Imm; |
3666 |
Op->ShifterImm.Imm = Imm; |
| 3667 |
Op->StartLoc = S; |
3667 |
Op->StartLoc = S; |
| 3668 |
Op->EndLoc = E; |
3668 |
Op->EndLoc = E; |
| 3669 |
return Op; |
3669 |
return Op; |
| 3670 |
} |
3670 |
} |
| 3671 |
|
3671 |
|
| 3672 |
static std::unique_ptr CreateRotImm(unsigned Imm, SMLoc S, |
3672 |
static std::unique_ptr CreateRotImm(unsigned Imm, SMLoc S, |
| 3673 |
SMLoc E) { |
3673 |
SMLoc E) { |
| 3674 |
auto Op = std::make_unique(k_RotateImmediate); |
3674 |
auto Op = std::make_unique(k_RotateImmediate); |
| 3675 |
Op->RotImm.Imm = Imm; |
3675 |
Op->RotImm.Imm = Imm; |
| 3676 |
Op->StartLoc = S; |
3676 |
Op->StartLoc = S; |
| 3677 |
Op->EndLoc = E; |
3677 |
Op->EndLoc = E; |
| 3678 |
return Op; |
3678 |
return Op; |
| 3679 |
} |
3679 |
} |
| 3680 |
|
3680 |
|
| 3681 |
static std::unique_ptr CreateModImm(unsigned Bits, unsigned Rot, |
3681 |
static std::unique_ptr CreateModImm(unsigned Bits, unsigned Rot, |
| 3682 |
SMLoc S, SMLoc E) { |
3682 |
SMLoc S, SMLoc E) { |
| 3683 |
auto Op = std::make_unique(k_ModifiedImmediate); |
3683 |
auto Op = std::make_unique(k_ModifiedImmediate); |
| 3684 |
Op->ModImm.Bits = Bits; |
3684 |
Op->ModImm.Bits = Bits; |
| 3685 |
Op->ModImm.Rot = Rot; |
3685 |
Op->ModImm.Rot = Rot; |
| 3686 |
Op->StartLoc = S; |
3686 |
Op->StartLoc = S; |
| 3687 |
Op->EndLoc = E; |
3687 |
Op->EndLoc = E; |
| 3688 |
return Op; |
3688 |
return Op; |
| 3689 |
} |
3689 |
} |
| 3690 |
|
3690 |
|
| 3691 |
static std::unique_ptr |
3691 |
static std::unique_ptr |
| 3692 |
CreateConstantPoolImm(const MCExpr *Val, SMLoc S, SMLoc E) { |
3692 |
CreateConstantPoolImm(const MCExpr *Val, SMLoc S, SMLoc E) { |
| 3693 |
auto Op = std::make_unique(k_ConstantPoolImmediate); |
3693 |
auto Op = std::make_unique(k_ConstantPoolImmediate); |
| 3694 |
Op->Imm.Val = Val; |
3694 |
Op->Imm.Val = Val; |
| 3695 |
Op->StartLoc = S; |
3695 |
Op->StartLoc = S; |
| 3696 |
Op->EndLoc = E; |
3696 |
Op->EndLoc = E; |
| 3697 |
return Op; |
3697 |
return Op; |
| 3698 |
} |
3698 |
} |
| 3699 |
|
3699 |
|
| 3700 |
static std::unique_ptr |
3700 |
static std::unique_ptr |
| 3701 |
CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) { |
3701 |
CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) { |
| 3702 |
auto Op = std::make_unique(k_BitfieldDescriptor); |
3702 |
auto Op = std::make_unique(k_BitfieldDescriptor); |
| 3703 |
Op->Bitfield.LSB = LSB; |
3703 |
Op->Bitfield.LSB = LSB; |
| 3704 |
Op->Bitfield.Width = Width; |
3704 |
Op->Bitfield.Width = Width; |
| 3705 |
Op->StartLoc = S; |
3705 |
Op->StartLoc = S; |
| 3706 |
Op->EndLoc = E; |
3706 |
Op->EndLoc = E; |
| 3707 |
return Op; |
3707 |
return Op; |
| 3708 |
} |
3708 |
} |
| 3709 |
|
3709 |
|
| 3710 |
static std::unique_ptr |
3710 |
static std::unique_ptr |
| 3711 |
CreateRegList(SmallVectorImpl> &Regs, |
3711 |
CreateRegList(SmallVectorImpl> &Regs, |
| 3712 |
SMLoc StartLoc, SMLoc EndLoc) { |
3712 |
SMLoc StartLoc, SMLoc EndLoc) { |
| 3713 |
assert(Regs.size() > 0 && "RegList contains no registers?"); |
3713 |
assert(Regs.size() > 0 && "RegList contains no registers?"); |
| 3714 |
KindTy Kind = k_RegisterList; |
3714 |
KindTy Kind = k_RegisterList; |
| 3715 |
|
3715 |
|
| 3716 |
if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains( |
3716 |
if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains( |
| 3717 |
Regs.front().second)) { |
3717 |
Regs.front().second)) { |
| 3718 |
if (Regs.back().second == ARM::VPR) |
3718 |
if (Regs.back().second == ARM::VPR) |
| 3719 |
Kind = k_FPDRegisterListWithVPR; |
3719 |
Kind = k_FPDRegisterListWithVPR; |
| 3720 |
else |
3720 |
else |
| 3721 |
Kind = k_DPRRegisterList; |
3721 |
Kind = k_DPRRegisterList; |
| 3722 |
} else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains( |
3722 |
} else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains( |
| 3723 |
Regs.front().second)) { |
3723 |
Regs.front().second)) { |
| 3724 |
if (Regs.back().second == ARM::VPR) |
3724 |
if (Regs.back().second == ARM::VPR) |
| 3725 |
Kind = k_FPSRegisterListWithVPR; |
3725 |
Kind = k_FPSRegisterListWithVPR; |
| 3726 |
else |
3726 |
else |
| 3727 |
Kind = k_SPRRegisterList; |
3727 |
Kind = k_SPRRegisterList; |
| 3728 |
} |
3728 |
} |
| 3729 |
|
3729 |
|
| 3730 |
if (Kind == k_RegisterList && Regs.back().second == ARM::APSR) |
3730 |
if (Kind == k_RegisterList && Regs.back().second == ARM::APSR) |
| 3731 |
Kind = k_RegisterListWithAPSR; |
3731 |
Kind = k_RegisterListWithAPSR; |
| 3732 |
|
3732 |
|
| 3733 |
assert(llvm::is_sorted(Regs) && "Register list must be sorted by encoding"); |
3733 |
assert(llvm::is_sorted(Regs) && "Register list must be sorted by encoding"); |
| 3734 |
|
3734 |
|
| 3735 |
auto Op = std::make_unique(Kind); |
3735 |
auto Op = std::make_unique(Kind); |
| 3736 |
for (const auto &P : Regs) |
3736 |
for (const auto &P : Regs) |
| 3737 |
Op->Registers.push_back(P.second); |
3737 |
Op->Registers.push_back(P.second); |
| 3738 |
|
3738 |
|
| 3739 |
Op->StartLoc = StartLoc; |
3739 |
Op->StartLoc = StartLoc; |
| 3740 |
Op->EndLoc = EndLoc; |
3740 |
Op->EndLoc = EndLoc; |
| 3741 |
return Op; |
3741 |
return Op; |
| 3742 |
} |
3742 |
} |
| 3743 |
|
3743 |
|
| 3744 |
static std::unique_ptr CreateVectorList(unsigned RegNum, |
3744 |
static std::unique_ptr CreateVectorList(unsigned RegNum, |
| 3745 |
unsigned Count, |
3745 |
unsigned Count, |
| 3746 |
bool isDoubleSpaced, |
3746 |
bool isDoubleSpaced, |
| 3747 |
SMLoc S, SMLoc E) { |
3747 |
SMLoc S, SMLoc E) { |
| 3748 |
auto Op = std::make_unique(k_VectorList); |
3748 |
auto Op = std::make_unique(k_VectorList); |
| 3749 |
Op->VectorList.RegNum = RegNum; |
3749 |
Op->VectorList.RegNum = RegNum; |
| 3750 |
Op->VectorList.Count = Count; |
3750 |
Op->VectorList.Count = Count; |
| 3751 |
Op->VectorList.isDoubleSpaced = isDoubleSpaced; |
3751 |
Op->VectorList.isDoubleSpaced = isDoubleSpaced; |
| 3752 |
Op->StartLoc = S; |
3752 |
Op->StartLoc = S; |
| 3753 |
Op->EndLoc = E; |
3753 |
Op->EndLoc = E; |
| 3754 |
return Op; |
3754 |
return Op; |
| 3755 |
} |
3755 |
} |
| 3756 |
|
3756 |
|
| 3757 |
static std::unique_ptr |
3757 |
static std::unique_ptr |
| 3758 |
CreateVectorListAllLanes(unsigned RegNum, unsigned Count, bool isDoubleSpaced, |
3758 |
CreateVectorListAllLanes(unsigned RegNum, unsigned Count, bool isDoubleSpaced, |
| 3759 |
SMLoc S, SMLoc E) { |
3759 |
SMLoc S, SMLoc E) { |
| 3760 |
auto Op = std::make_unique(k_VectorListAllLanes); |
3760 |
auto Op = std::make_unique(k_VectorListAllLanes); |
| 3761 |
Op->VectorList.RegNum = RegNum; |
3761 |
Op->VectorList.RegNum = RegNum; |
| 3762 |
Op->VectorList.Count = Count; |
3762 |
Op->VectorList.Count = Count; |
| 3763 |
Op->VectorList.isDoubleSpaced = isDoubleSpaced; |
3763 |
Op->VectorList.isDoubleSpaced = isDoubleSpaced; |
| 3764 |
Op->StartLoc = S; |
3764 |
Op->StartLoc = S; |
| 3765 |
Op->EndLoc = E; |
3765 |
Op->EndLoc = E; |
| 3766 |
return Op; |
3766 |
return Op; |
| 3767 |
} |
3767 |
} |
| 3768 |
|
3768 |
|
| 3769 |
static std::unique_ptr |
3769 |
static std::unique_ptr |
| 3770 |
CreateVectorListIndexed(unsigned RegNum, unsigned Count, unsigned Index, |
3770 |
CreateVectorListIndexed(unsigned RegNum, unsigned Count, unsigned Index, |
| 3771 |
bool isDoubleSpaced, SMLoc S, SMLoc E) { |
3771 |
bool isDoubleSpaced, SMLoc S, SMLoc E) { |
| 3772 |
auto Op = std::make_unique(k_VectorListIndexed); |
3772 |
auto Op = std::make_unique(k_VectorListIndexed); |
| 3773 |
Op->VectorList.RegNum = RegNum; |
3773 |
Op->VectorList.RegNum = RegNum; |
| 3774 |
Op->VectorList.Count = Count; |
3774 |
Op->VectorList.Count = Count; |
| 3775 |
Op->VectorList.LaneIndex = Index; |
3775 |
Op->VectorList.LaneIndex = Index; |
| 3776 |
Op->VectorList.isDoubleSpaced = isDoubleSpaced; |
3776 |
Op->VectorList.isDoubleSpaced = isDoubleSpaced; |
| 3777 |
Op->StartLoc = S; |
3777 |
Op->StartLoc = S; |
| 3778 |
Op->EndLoc = E; |
3778 |
Op->EndLoc = E; |
| 3779 |
return Op; |
3779 |
return Op; |
| 3780 |
} |
3780 |
} |
| 3781 |
|
3781 |
|
| 3782 |
static std::unique_ptr |
3782 |
static std::unique_ptr |
| 3783 |
CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) { |
3783 |
CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) { |
| 3784 |
auto Op = std::make_unique(k_VectorIndex); |
3784 |
auto Op = std::make_unique(k_VectorIndex); |
| 3785 |
Op->VectorIndex.Val = Idx; |
3785 |
Op->VectorIndex.Val = Idx; |
| 3786 |
Op->StartLoc = S; |
3786 |
Op->StartLoc = S; |
| 3787 |
Op->EndLoc = E; |
3787 |
Op->EndLoc = E; |
| 3788 |
return Op; |
3788 |
return Op; |
| 3789 |
} |
3789 |
} |
| 3790 |
|
3790 |
|
| 3791 |
static std::unique_ptr CreateImm(const MCExpr *Val, SMLoc S, |
3791 |
static std::unique_ptr CreateImm(const MCExpr *Val, SMLoc S, |
| 3792 |
SMLoc E) { |
3792 |
SMLoc E) { |
| 3793 |
auto Op = std::make_unique(k_Immediate); |
3793 |
auto Op = std::make_unique(k_Immediate); |
| 3794 |
Op->Imm.Val = Val; |
3794 |
Op->Imm.Val = Val; |
| 3795 |
Op->StartLoc = S; |
3795 |
Op->StartLoc = S; |
| 3796 |
Op->EndLoc = E; |
3796 |
Op->EndLoc = E; |
| 3797 |
return Op; |
3797 |
return Op; |
| 3798 |
} |
3798 |
} |
| 3799 |
|
3799 |
|
| 3800 |
static std::unique_ptr |
3800 |
static std::unique_ptr |
| 3801 |
CreateMem(unsigned BaseRegNum, const MCExpr *OffsetImm, unsigned OffsetRegNum, |
3801 |
CreateMem(unsigned BaseRegNum, const MCExpr *OffsetImm, unsigned OffsetRegNum, |
| 3802 |
ARM_AM::ShiftOpc ShiftType, unsigned ShiftImm, unsigned Alignment, |
3802 |
ARM_AM::ShiftOpc ShiftType, unsigned ShiftImm, unsigned Alignment, |
| 3803 |
bool isNegative, SMLoc S, SMLoc E, SMLoc AlignmentLoc = SMLoc()) { |
3803 |
bool isNegative, SMLoc S, SMLoc E, SMLoc AlignmentLoc = SMLoc()) { |
| 3804 |
auto Op = std::make_unique(k_Memory); |
3804 |
auto Op = std::make_unique(k_Memory); |
| 3805 |
Op->Memory.BaseRegNum = BaseRegNum; |
3805 |
Op->Memory.BaseRegNum = BaseRegNum; |
| 3806 |
Op->Memory.OffsetImm = OffsetImm; |
3806 |
Op->Memory.OffsetImm = OffsetImm; |
| 3807 |
Op->Memory.OffsetRegNum = OffsetRegNum; |
3807 |
Op->Memory.OffsetRegNum = OffsetRegNum; |
| 3808 |
Op->Memory.ShiftType = ShiftType; |
3808 |
Op->Memory.ShiftType = ShiftType; |
| 3809 |
Op->Memory.ShiftImm = ShiftImm; |
3809 |
Op->Memory.ShiftImm = ShiftImm; |
| 3810 |
Op->Memory.Alignment = Alignment; |
3810 |
Op->Memory.Alignment = Alignment; |
| 3811 |
Op->Memory.isNegative = isNegative; |
3811 |
Op->Memory.isNegative = isNegative; |
| 3812 |
Op->StartLoc = S; |
3812 |
Op->StartLoc = S; |
| 3813 |
Op->EndLoc = E; |
3813 |
Op->EndLoc = E; |
| 3814 |
Op->AlignmentLoc = AlignmentLoc; |
3814 |
Op->AlignmentLoc = AlignmentLoc; |
| 3815 |
return Op; |
3815 |
return Op; |
| 3816 |
} |
3816 |
} |
| 3817 |
|
3817 |
|
| 3818 |
static std::unique_ptr |
3818 |
static std::unique_ptr |
| 3819 |
CreatePostIdxReg(unsigned RegNum, bool isAdd, ARM_AM::ShiftOpc ShiftTy, |
3819 |
CreatePostIdxReg(unsigned RegNum, bool isAdd, ARM_AM::ShiftOpc ShiftTy, |
| 3820 |
unsigned ShiftImm, SMLoc S, SMLoc E) { |
3820 |
unsigned ShiftImm, SMLoc S, SMLoc E) { |
| 3821 |
auto Op = std::make_unique(k_PostIndexRegister); |
3821 |
auto Op = std::make_unique(k_PostIndexRegister); |
| 3822 |
Op->PostIdxReg.RegNum = RegNum; |
3822 |
Op->PostIdxReg.RegNum = RegNum; |
| 3823 |
Op->PostIdxReg.isAdd = isAdd; |
3823 |
Op->PostIdxReg.isAdd = isAdd; |
| 3824 |
Op->PostIdxReg.ShiftTy = ShiftTy; |
3824 |
Op->PostIdxReg.ShiftTy = ShiftTy; |
| 3825 |
Op->PostIdxReg.ShiftImm = ShiftImm; |
3825 |
Op->PostIdxReg.ShiftImm = ShiftImm; |
| 3826 |
Op->StartLoc = S; |
3826 |
Op->StartLoc = S; |
| 3827 |
Op->EndLoc = E; |
3827 |
Op->EndLoc = E; |
| 3828 |
return Op; |
3828 |
return Op; |
| 3829 |
} |
3829 |
} |
| 3830 |
|
3830 |
|
| 3831 |
static std::unique_ptr CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, |
3831 |
static std::unique_ptr CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, |
| 3832 |
SMLoc S) { |
3832 |
SMLoc S) { |
| 3833 |
auto Op = std::make_unique(k_MemBarrierOpt); |
3833 |
auto Op = std::make_unique(k_MemBarrierOpt); |
| 3834 |
Op->MBOpt.Val = Opt; |
3834 |
Op->MBOpt.Val = Opt; |
| 3835 |
Op->StartLoc = S; |
3835 |
Op->StartLoc = S; |
| 3836 |
Op->EndLoc = S; |
3836 |
Op->EndLoc = S; |
| 3837 |
return Op; |
3837 |
return Op; |
| 3838 |
} |
3838 |
} |
| 3839 |
|
3839 |
|
| 3840 |
static std::unique_ptr |
3840 |
static std::unique_ptr |
| 3841 |
CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, SMLoc S) { |
3841 |
CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, SMLoc S) { |
| 3842 |
auto Op = std::make_unique(k_InstSyncBarrierOpt); |
3842 |
auto Op = std::make_unique(k_InstSyncBarrierOpt); |
| 3843 |
Op->ISBOpt.Val = Opt; |
3843 |
Op->ISBOpt.Val = Opt; |
| 3844 |
Op->StartLoc = S; |
3844 |
Op->StartLoc = S; |
| 3845 |
Op->EndLoc = S; |
3845 |
Op->EndLoc = S; |
| 3846 |
return Op; |
3846 |
return Op; |
| 3847 |
} |
3847 |
} |
| 3848 |
|
3848 |
|
| 3849 |
static std::unique_ptr |
3849 |
static std::unique_ptr |
| 3850 |
CreateTraceSyncBarrierOpt(ARM_TSB::TraceSyncBOpt Opt, SMLoc S) { |
3850 |
CreateTraceSyncBarrierOpt(ARM_TSB::TraceSyncBOpt Opt, SMLoc S) { |
| 3851 |
auto Op = std::make_unique(k_TraceSyncBarrierOpt); |
3851 |
auto Op = std::make_unique(k_TraceSyncBarrierOpt); |
| 3852 |
Op->TSBOpt.Val = Opt; |
3852 |
Op->TSBOpt.Val = Opt; |
| 3853 |
Op->StartLoc = S; |
3853 |
Op->StartLoc = S; |
| 3854 |
Op->EndLoc = S; |
3854 |
Op->EndLoc = S; |
| 3855 |
return Op; |
3855 |
return Op; |
| 3856 |
} |
3856 |
} |
| 3857 |
|
3857 |
|
| 3858 |
static std::unique_ptr CreateProcIFlags(ARM_PROC::IFlags IFlags, |
3858 |
static std::unique_ptr CreateProcIFlags(ARM_PROC::IFlags IFlags, |
| 3859 |
SMLoc S) { |
3859 |
SMLoc S) { |
| 3860 |
auto Op = std::make_unique(k_ProcIFlags); |
3860 |
auto Op = std::make_unique(k_ProcIFlags); |
| 3861 |
Op->IFlags.Val = IFlags; |
3861 |
Op->IFlags.Val = IFlags; |
| 3862 |
Op->StartLoc = S; |
3862 |
Op->StartLoc = S; |
| 3863 |
Op->EndLoc = S; |
3863 |
Op->EndLoc = S; |
| 3864 |
return Op; |
3864 |
return Op; |
| 3865 |
} |
3865 |
} |
| 3866 |
|
3866 |
|
| 3867 |
static std::unique_ptr CreateMSRMask(unsigned MMask, SMLoc S) { |
3867 |
static std::unique_ptr CreateMSRMask(unsigned MMask, SMLoc S) { |
| 3868 |
auto Op = std::make_unique(k_MSRMask); |
3868 |
auto Op = std::make_unique(k_MSRMask); |
| 3869 |
Op->MMask.Val = MMask; |
3869 |
Op->MMask.Val = MMask; |
| 3870 |
Op->StartLoc = S; |
3870 |
Op->StartLoc = S; |
| 3871 |
Op->EndLoc = S; |
3871 |
Op->EndLoc = S; |
| 3872 |
return Op; |
3872 |
return Op; |
| 3873 |
} |
3873 |
} |
| 3874 |
|
3874 |
|
| 3875 |
static std::unique_ptr CreateBankedReg(unsigned Reg, SMLoc S) { |
3875 |
static std::unique_ptr CreateBankedReg(unsigned Reg, SMLoc S) { |
| 3876 |
auto Op = std::make_unique(k_BankedReg); |
3876 |
auto Op = std::make_unique(k_BankedReg); |
| 3877 |
Op->BankedReg.Val = Reg; |
3877 |
Op->BankedReg.Val = Reg; |
| 3878 |
Op->StartLoc = S; |
3878 |
Op->StartLoc = S; |
| 3879 |
Op->EndLoc = S; |
3879 |
Op->EndLoc = S; |
| 3880 |
return Op; |
3880 |
return Op; |
| 3881 |
} |
3881 |
} |
| 3882 |
}; |
3882 |
}; |
| 3883 |
|
3883 |
|
| 3884 |
} // end anonymous namespace. |
3884 |
} // end anonymous namespace. |
| 3885 |
|
3885 |
|
| 3886 |
void ARMOperand::print(raw_ostream &OS) const { |
3886 |
void ARMOperand::print(raw_ostream &OS) const { |
| 3887 |
auto RegName = [](MCRegister Reg) { |
3887 |
auto RegName = [](MCRegister Reg) { |
| 3888 |
if (Reg) |
3888 |
if (Reg) |
| 3889 |
return ARMInstPrinter::getRegisterName(Reg); |
3889 |
return ARMInstPrinter::getRegisterName(Reg); |
| 3890 |
else |
3890 |
else |
| 3891 |
return "noreg"; |
3891 |
return "noreg"; |
| 3892 |
}; |
3892 |
}; |
| 3893 |
|
3893 |
|
| 3894 |
switch (Kind) { |
3894 |
switch (Kind) { |
| 3895 |
case k_CondCode: |
3895 |
case k_CondCode: |
| 3896 |
OS << ""; |
3896 |
OS << ""; |
| 3897 |
break; |
3897 |
break; |
| 3898 |
case k_VPTPred: |
3898 |
case k_VPTPred: |
| 3899 |
OS << ""; |
3899 |
OS << ""; |
| 3900 |
break; |
3900 |
break; |
| 3901 |
case k_CCOut: |
3901 |
case k_CCOut: |
| 3902 |
OS << ""; |
3902 |
OS << ""; |
| 3903 |
break; |
3903 |
break; |
| 3904 |
case k_ITCondMask: { |
3904 |
case k_ITCondMask: { |
| 3905 |
static const char *const MaskStr[] = { |
3905 |
static const char *const MaskStr[] = { |
| 3906 |
"(invalid)", "(tttt)", "(ttt)", "(ttte)", |
3906 |
"(invalid)", "(tttt)", "(ttt)", "(ttte)", |
| 3907 |
"(tt)", "(ttet)", "(tte)", "(ttee)", |
3907 |
"(tt)", "(ttet)", "(tte)", "(ttee)", |
| 3908 |
"(t)", "(tett)", "(tet)", "(tete)", |
3908 |
"(t)", "(tett)", "(tet)", "(tete)", |
| 3909 |
"(te)", "(teet)", "(tee)", "(teee)", |
3909 |
"(te)", "(teet)", "(tee)", "(teee)", |
| 3910 |
}; |
3910 |
}; |
| 3911 |
assert((ITMask.Mask & 0xf) == ITMask.Mask); |
3911 |
assert((ITMask.Mask & 0xf) == ITMask.Mask); |
| 3912 |
OS << ""; |
3912 |
OS << ""; |
| 3913 |
break; |
3913 |
break; |
| 3914 |
} |
3914 |
} |
| 3915 |
case k_CoprocNum: |
3915 |
case k_CoprocNum: |
| 3916 |
OS << ""; |
3916 |
OS << ""; |
| 3917 |
break; |
3917 |
break; |
| 3918 |
case k_CoprocReg: |
3918 |
case k_CoprocReg: |
| 3919 |
OS << ""; |
3919 |
OS << ""; |
| 3920 |
break; |
3920 |
break; |
| 3921 |
case k_CoprocOption: |
3921 |
case k_CoprocOption: |
| 3922 |
OS << ""; |
3922 |
OS << ""; |
| 3923 |
break; |
3923 |
break; |
| 3924 |
case k_MSRMask: |
3924 |
case k_MSRMask: |
| 3925 |
OS << ""; |
3925 |
OS << ""; |
| 3926 |
break; |
3926 |
break; |
| 3927 |
case k_BankedReg: |
3927 |
case k_BankedReg: |
| 3928 |
OS << ""; |
3928 |
OS << ""; |
| 3929 |
break; |
3929 |
break; |
| 3930 |
case k_Immediate: |
3930 |
case k_Immediate: |
| 3931 |
OS << *getImm(); |
3931 |
OS << *getImm(); |
| 3932 |
break; |
3932 |
break; |
| 3933 |
case k_MemBarrierOpt: |
3933 |
case k_MemBarrierOpt: |
| 3934 |
OS << ""; |
3934 |
OS << ""; |
| 3935 |
break; |
3935 |
break; |
| 3936 |
case k_InstSyncBarrierOpt: |
3936 |
case k_InstSyncBarrierOpt: |
| 3937 |
OS << ""; |
3937 |
OS << ""; |
| 3938 |
break; |
3938 |
break; |
| 3939 |
case k_TraceSyncBarrierOpt: |
3939 |
case k_TraceSyncBarrierOpt: |
| 3940 |
OS << ""; |
3940 |
OS << ""; |
| 3941 |
break; |
3941 |
break; |
| 3942 |
case k_Memory: |
3942 |
case k_Memory: |
| 3943 |
OS << "
| 3943 |
OS << "
| |
| 3944 |
if (Memory.BaseRegNum) |
3944 |
if (Memory.BaseRegNum) |
| 3945 |
OS << " base:" << RegName(Memory.BaseRegNum); |
3945 |
OS << " base:" << RegName(Memory.BaseRegNum); |
| 3946 |
if (Memory.OffsetImm) |
3946 |
if (Memory.OffsetImm) |
| 3947 |
OS << " offset-imm:" << *Memory.OffsetImm; |
3947 |
OS << " offset-imm:" << *Memory.OffsetImm; |
| 3948 |
if (Memory.OffsetRegNum) |
3948 |
if (Memory.OffsetRegNum) |
| 3949 |
OS << " offset-reg:" << (Memory.isNegative ? "-" : "") |
3949 |
OS << " offset-reg:" << (Memory.isNegative ? "-" : "") |
| 3950 |
<< RegName(Memory.OffsetRegNum); |
3950 |
<< RegName(Memory.OffsetRegNum); |
| 3951 |
if (Memory.ShiftType != ARM_AM::no_shift) { |
3951 |
if (Memory.ShiftType != ARM_AM::no_shift) { |
| 3952 |
OS << " shift-type:" << ARM_AM::getShiftOpcStr(Memory.ShiftType); |
3952 |
OS << " shift-type:" << ARM_AM::getShiftOpcStr(Memory.ShiftType); |
| 3953 |
OS << " shift-imm:" << Memory.ShiftImm; |
3953 |
OS << " shift-imm:" << Memory.ShiftImm; |
| 3954 |
} |
3954 |
} |
| 3955 |
if (Memory.Alignment) |
3955 |
if (Memory.Alignment) |
| 3956 |
OS << " alignment:" << Memory.Alignment; |
3956 |
OS << " alignment:" << Memory.Alignment; |
| 3957 |
OS << ">"; |
3957 |
OS << ">"; |
| 3958 |
break; |
3958 |
break; |
| 3959 |
case k_PostIndexRegister: |
3959 |
case k_PostIndexRegister: |
| 3960 |
OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-") |
3960 |
OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-") |
| 3961 |
<< RegName(PostIdxReg.RegNum); |
3961 |
<< RegName(PostIdxReg.RegNum); |
| 3962 |
if (PostIdxReg.ShiftTy != ARM_AM::no_shift) |
3962 |
if (PostIdxReg.ShiftTy != ARM_AM::no_shift) |
| 3963 |
OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " " |
3963 |
OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " " |
| 3964 |
<< PostIdxReg.ShiftImm; |
3964 |
<< PostIdxReg.ShiftImm; |
| 3965 |
OS << ">"; |
3965 |
OS << ">"; |
| 3966 |
break; |
3966 |
break; |
| 3967 |
case k_ProcIFlags: { |
3967 |
case k_ProcIFlags: { |
| 3968 |
OS << "
| 3968 |
OS << "
| |
| 3969 |
unsigned IFlags = getProcIFlags(); |
3969 |
unsigned IFlags = getProcIFlags(); |
| 3970 |
for (int i=2; i >= 0; --i) |
3970 |
for (int i=2; i >= 0; --i) |
| 3971 |
if (IFlags & (1 << i)) |
3971 |
if (IFlags & (1 << i)) |
| 3972 |
OS << ARM_PROC::IFlagsToString(1 << i); |
3972 |
OS << ARM_PROC::IFlagsToString(1 << i); |
| 3973 |
OS << ">"; |
3973 |
OS << ">"; |
| 3974 |
break; |
3974 |
break; |
| 3975 |
} |
3975 |
} |
| 3976 |
case k_Register: |
3976 |
case k_Register: |
| 3977 |
OS << ""; |
3977 |
OS << ""; |
| 3978 |
break; |
3978 |
break; |
| 3979 |
case k_ShifterImmediate: |
3979 |
case k_ShifterImmediate: |
| 3980 |
OS << "
| 3980 |
OS << "
| |
| 3981 |
<< " #" << ShifterImm.Imm << ">"; |
3981 |
<< " #" << ShifterImm.Imm << ">"; |
| 3982 |
break; |
3982 |
break; |
| 3983 |
case k_ShiftedRegister: |
3983 |
case k_ShiftedRegister: |
| 3984 |
OS << "
| 3984 |
OS << "
| |
| 3985 |
<< ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy) << " " |
3985 |
<< ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy) << " " |
| 3986 |
<< RegName(RegShiftedReg.ShiftReg) << ">"; |
3986 |
<< RegName(RegShiftedReg.ShiftReg) << ">"; |
| 3987 |
break; |
3987 |
break; |
| 3988 |
case k_ShiftedImmediate: |
3988 |
case k_ShiftedImmediate: |
| 3989 |
OS << "
| 3989 |
OS << "
| |
| 3990 |
<< ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy) << " #" |
3990 |
<< ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy) << " #" |
| 3991 |
<< RegShiftedImm.ShiftImm << ">"; |
3991 |
<< RegShiftedImm.ShiftImm << ">"; |
| 3992 |
break; |
3992 |
break; |
| 3993 |
case k_RotateImmediate: |
3993 |
case k_RotateImmediate: |
| 3994 |
OS << ""; |
3994 |
OS << ""; |
| 3995 |
break; |
3995 |
break; |
| 3996 |
case k_ModifiedImmediate: |
3996 |
case k_ModifiedImmediate: |
| 3997 |
OS << "
| 3997 |
OS << "
| |
| 3998 |
<< ModImm.Rot << ")>"; |
3998 |
<< ModImm.Rot << ")>"; |
| 3999 |
break; |
3999 |
break; |
| 4000 |
case k_ConstantPoolImmediate: |
4000 |
case k_ConstantPoolImmediate: |
| 4001 |
OS << "
| 4001 |
OS << "
| |
| 4002 |
break; |
4002 |
break; |
| 4003 |
case k_BitfieldDescriptor: |
4003 |
case k_BitfieldDescriptor: |
| 4004 |
OS << "
| 4004 |
OS << "
| |
| 4005 |
<< ", width: " << Bitfield.Width << ">"; |
4005 |
<< ", width: " << Bitfield.Width << ">"; |
| 4006 |
break; |
4006 |
break; |
| 4007 |
case k_RegisterList: |
4007 |
case k_RegisterList: |
| 4008 |
case k_RegisterListWithAPSR: |
4008 |
case k_RegisterListWithAPSR: |
| 4009 |
case k_DPRRegisterList: |
4009 |
case k_DPRRegisterList: |
| 4010 |
case k_SPRRegisterList: |
4010 |
case k_SPRRegisterList: |
| 4011 |
case k_FPSRegisterListWithVPR: |
4011 |
case k_FPSRegisterListWithVPR: |
| 4012 |
case k_FPDRegisterListWithVPR: { |
4012 |
case k_FPDRegisterListWithVPR: { |
| 4013 |
OS << "
| 4013 |
OS << "
| |
| 4014 |
|
4014 |
|
| 4015 |
const SmallVectorImpl &RegList = getRegList(); |
4015 |
const SmallVectorImpl &RegList = getRegList(); |
| 4016 |
for (SmallVectorImpl::const_iterator |
4016 |
for (SmallVectorImpl::const_iterator |
| 4017 |
I = RegList.begin(), E = RegList.end(); I != E; ) { |
4017 |
I = RegList.begin(), E = RegList.end(); I != E; ) { |
| 4018 |
OS << RegName(*I); |
4018 |
OS << RegName(*I); |
| 4019 |
if (++I < E) OS << ", "; |
4019 |
if (++I < E) OS << ", "; |
| 4020 |
} |
4020 |
} |
| 4021 |
|
4021 |
|
| 4022 |
OS << ">"; |
4022 |
OS << ">"; |
| 4023 |
break; |
4023 |
break; |
| 4024 |
} |
4024 |
} |
| 4025 |
case k_VectorList: |
4025 |
case k_VectorList: |
| 4026 |
OS << "
| 4026 |
OS << "
| |
| 4027 |
<< RegName(VectorList.RegNum) << ">"; |
4027 |
<< RegName(VectorList.RegNum) << ">"; |
| 4028 |
break; |
4028 |
break; |
| 4029 |
case k_VectorListAllLanes: |
4029 |
case k_VectorListAllLanes: |
| 4030 |
OS << "
| 4030 |
OS << "
| |
| 4031 |
<< RegName(VectorList.RegNum) << ">"; |
4031 |
<< RegName(VectorList.RegNum) << ">"; |
| 4032 |
break; |
4032 |
break; |
| 4033 |
case k_VectorListIndexed: |
4033 |
case k_VectorListIndexed: |
| 4034 |
OS << "
| 4034 |
OS << "
| |
| 4035 |
<< VectorList.Count << " * " << RegName(VectorList.RegNum) << ">"; |
4035 |
<< VectorList.Count << " * " << RegName(VectorList.RegNum) << ">"; |
| 4036 |
break; |
4036 |
break; |
| 4037 |
case k_Token: |
4037 |
case k_Token: |
| 4038 |
OS << "'" << getToken() << "'"; |
4038 |
OS << "'" << getToken() << "'"; |
| 4039 |
break; |
4039 |
break; |
| 4040 |
case k_VectorIndex: |
4040 |
case k_VectorIndex: |
| 4041 |
OS << ""; |
4041 |
OS << ""; |
| 4042 |
break; |
4042 |
break; |
| 4043 |
} |
4043 |
} |
| 4044 |
} |
4044 |
} |
| 4045 |
|
4045 |
|
| 4046 |
/// @name Auto-generated Match Functions |
4046 |
/// @name Auto-generated Match Functions |
| 4047 |
/// { |
4047 |
/// { |
| 4048 |
|
4048 |
|
| 4049 |
static unsigned MatchRegisterName(StringRef Name); |
4049 |
static unsigned MatchRegisterName(StringRef Name); |
| 4050 |
|
4050 |
|
| 4051 |
/// } |
4051 |
/// } |
| 4052 |
|
4052 |
|
| 4053 |
bool ARMAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc, |
4053 |
bool ARMAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc, |
| 4054 |
SMLoc &EndLoc) { |
4054 |
SMLoc &EndLoc) { |
| 4055 |
const AsmToken &Tok = getParser().getTok(); |
4055 |
const AsmToken &Tok = getParser().getTok(); |
| 4056 |
StartLoc = Tok.getLoc(); |
4056 |
StartLoc = Tok.getLoc(); |
| 4057 |
EndLoc = Tok.getEndLoc(); |
4057 |
EndLoc = Tok.getEndLoc(); |
| 4058 |
RegNo = tryParseRegister(); |
4058 |
RegNo = tryParseRegister(); |
| 4059 |
|
4059 |
|
| 4060 |
return (RegNo == (unsigned)-1); |
4060 |
return (RegNo == (unsigned)-1); |
| 4061 |
} |
4061 |
} |
| 4062 |
|
4062 |
|
| 4063 |
OperandMatchResultTy ARMAsmParser::tryParseRegister(MCRegister &RegNo, |
4063 |
OperandMatchResultTy ARMAsmParser::tryParseRegister(MCRegister &RegNo, |
| 4064 |
SMLoc &StartLoc, |
4064 |
SMLoc &StartLoc, |
| 4065 |
SMLoc &EndLoc) { |
4065 |
SMLoc &EndLoc) { |
| 4066 |
if (parseRegister(RegNo, StartLoc, EndLoc)) |
4066 |
if (parseRegister(RegNo, StartLoc, EndLoc)) |
| 4067 |
return MatchOperand_NoMatch; |
4067 |
return MatchOperand_NoMatch; |
| 4068 |
return MatchOperand_Success; |
4068 |
return MatchOperand_Success; |
| 4069 |
} |
4069 |
} |
| 4070 |
|
4070 |
|
| 4071 |
/// Try to parse a register name. The token must be an Identifier when called, |
4071 |
/// Try to parse a register name. The token must be an Identifier when called, |
| 4072 |
/// and if it is a register name the token is eaten and the register number is |
4072 |
/// and if it is a register name the token is eaten and the register number is |
| 4073 |
/// returned. Otherwise return -1. |
4073 |
/// returned. Otherwise return -1. |
| 4074 |
int ARMAsmParser::tryParseRegister() { |
4074 |
int ARMAsmParser::tryParseRegister() { |
| 4075 |
MCAsmParser &Parser = getParser(); |
4075 |
MCAsmParser &Parser = getParser(); |
| 4076 |
const AsmToken &Tok = Parser.getTok(); |
4076 |
const AsmToken &Tok = Parser.getTok(); |
| 4077 |
if (Tok.isNot(AsmToken::Identifier)) return -1; |
4077 |
if (Tok.isNot(AsmToken::Identifier)) return -1; |
| 4078 |
|
4078 |
|
| 4079 |
std::string lowerCase = Tok.getString().lower(); |
4079 |
std::string lowerCase = Tok.getString().lower(); |
| 4080 |
unsigned RegNum = MatchRegisterName(lowerCase); |
4080 |
unsigned RegNum = MatchRegisterName(lowerCase); |
| 4081 |
if (!RegNum) { |
4081 |
if (!RegNum) { |
| 4082 |
RegNum = StringSwitch(lowerCase) |
4082 |
RegNum = StringSwitch(lowerCase) |
| 4083 |
.Case("r13", ARM::SP) |
4083 |
.Case("r13", ARM::SP) |
| 4084 |
.Case("r14", ARM::LR) |
4084 |
.Case("r14", ARM::LR) |
| 4085 |
.Case("r15", ARM::PC) |
4085 |
.Case("r15", ARM::PC) |
| 4086 |
.Case("ip", ARM::R12) |
4086 |
.Case("ip", ARM::R12) |
| 4087 |
// Additional register name aliases for 'gas' compatibility. |
4087 |
// Additional register name aliases for 'gas' compatibility. |
| 4088 |
.Case("a1", ARM::R0) |
4088 |
.Case("a1", ARM::R0) |
| 4089 |
.Case("a2", ARM::R1) |
4089 |
.Case("a2", ARM::R1) |
| 4090 |
.Case("a3", ARM::R2) |
4090 |
.Case("a3", ARM::R2) |
| 4091 |
.Case("a4", ARM::R3) |
4091 |
.Case("a4", ARM::R3) |
| 4092 |
.Case("v1", ARM::R4) |
4092 |
.Case("v1", ARM::R4) |
| 4093 |
.Case("v2", ARM::R5) |
4093 |
.Case("v2", ARM::R5) |
| 4094 |
.Case("v3", ARM::R6) |
4094 |
.Case("v3", ARM::R6) |
| 4095 |
.Case("v4", ARM::R7) |
4095 |
.Case("v4", ARM::R7) |
| 4096 |
.Case("v5", ARM::R8) |
4096 |
.Case("v5", ARM::R8) |
| 4097 |
.Case("v6", ARM::R9) |
4097 |
.Case("v6", ARM::R9) |
| 4098 |
.Case("v7", ARM::R10) |
4098 |
.Case("v7", ARM::R10) |
| 4099 |
.Case("v8", ARM::R11) |
4099 |
.Case("v8", ARM::R11) |
| 4100 |
.Case("sb", ARM::R9) |
4100 |
.Case("sb", ARM::R9) |
| 4101 |
.Case("sl", ARM::R10) |
4101 |
.Case("sl", ARM::R10) |
| 4102 |
.Case("fp", ARM::R11) |
4102 |
.Case("fp", ARM::R11) |
| 4103 |
.Default(0); |
4103 |
.Default(0); |
| 4104 |
} |
4104 |
} |
| 4105 |
if (!RegNum) { |
4105 |
if (!RegNum) { |
| 4106 |
// Check for aliases registered via .req. Canonicalize to lower case. |
4106 |
// Check for aliases registered via .req. Canonicalize to lower case. |
| 4107 |
// That's more consistent since register names are case insensitive, and |
4107 |
// That's more consistent since register names are case insensitive, and |
| 4108 |
// it's how the original entry was passed in from MC/MCParser/AsmParser. |
4108 |
// it's how the original entry was passed in from MC/MCParser/AsmParser. |
| 4109 |
StringMap::const_iterator Entry = RegisterReqs.find(lowerCase); |
4109 |
StringMap::const_iterator Entry = RegisterReqs.find(lowerCase); |
| 4110 |
// If no match, return failure. |
4110 |
// If no match, return failure. |
| 4111 |
if (Entry == RegisterReqs.end()) |
4111 |
if (Entry == RegisterReqs.end()) |
| 4112 |
return -1; |
4112 |
return -1; |
| 4113 |
Parser.Lex(); // Eat identifier token. |
4113 |
Parser.Lex(); // Eat identifier token. |
| 4114 |
return Entry->getValue(); |
4114 |
return Entry->getValue(); |
| 4115 |
} |
4115 |
} |
| 4116 |
|
4116 |
|
| 4117 |
// Some FPUs only have 16 D registers, so D16-D31 are invalid |
4117 |
// Some FPUs only have 16 D registers, so D16-D31 are invalid |
| 4118 |
if (!hasD32() && RegNum >= ARM::D16 && RegNum <= ARM::D31) |
4118 |
if (!hasD32() && RegNum >= ARM::D16 && RegNum <= ARM::D31) |
| 4119 |
return -1; |
4119 |
return -1; |
| 4120 |
|
4120 |
|
| 4121 |
Parser.Lex(); // Eat identifier token. |
4121 |
Parser.Lex(); // Eat identifier token. |
| 4122 |
|
4122 |
|
| 4123 |
return RegNum; |
4123 |
return RegNum; |
| 4124 |
} |
4124 |
} |
| 4125 |
|
4125 |
|
| 4126 |
// Try to parse a shifter (e.g., "lsl "). On success, return 0. |
4126 |
// Try to parse a shifter (e.g., "lsl "). On success, return 0. |
| 4127 |
// If a recoverable error occurs, return 1. If an irrecoverable error |
4127 |
// If a recoverable error occurs, return 1. If an irrecoverable error |
| 4128 |
// occurs, return -1. An irrecoverable error is one where tokens have been |
4128 |
// occurs, return -1. An irrecoverable error is one where tokens have been |
| 4129 |
// consumed in the process of trying to parse the shifter (i.e., when it is |
4129 |
// consumed in the process of trying to parse the shifter (i.e., when it is |
| 4130 |
// indeed a shifter operand, but malformed). |
4130 |
// indeed a shifter operand, but malformed). |
| 4131 |
int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) { |
4131 |
int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) { |
| 4132 |
MCAsmParser &Parser = getParser(); |
4132 |
MCAsmParser &Parser = getParser(); |
| 4133 |
SMLoc S = Parser.getTok().getLoc(); |
4133 |
SMLoc S = Parser.getTok().getLoc(); |
| 4134 |
const AsmToken &Tok = Parser.getTok(); |
4134 |
const AsmToken &Tok = Parser.getTok(); |
| 4135 |
if (Tok.isNot(AsmToken::Identifier)) |
4135 |
if (Tok.isNot(AsmToken::Identifier)) |
| 4136 |
return -1; |
4136 |
return -1; |
| 4137 |
|
4137 |
|
| 4138 |
std::string lowerCase = Tok.getString().lower(); |
4138 |
std::string lowerCase = Tok.getString().lower(); |
| 4139 |
ARM_AM::ShiftOpc ShiftTy = StringSwitch(lowerCase) |
4139 |
ARM_AM::ShiftOpc ShiftTy = StringSwitch(lowerCase) |
| 4140 |
.Case("asl", ARM_AM::lsl) |
4140 |
.Case("asl", ARM_AM::lsl) |
| 4141 |
.Case("lsl", ARM_AM::lsl) |
4141 |
.Case("lsl", ARM_AM::lsl) |
| 4142 |
.Case("lsr", ARM_AM::lsr) |
4142 |
.Case("lsr", ARM_AM::lsr) |
| 4143 |
.Case("asr", ARM_AM::asr) |
4143 |
.Case("asr", ARM_AM::asr) |
| 4144 |
.Case("ror", ARM_AM::ror) |
4144 |
.Case("ror", ARM_AM::ror) |
| 4145 |
.Case("rrx", ARM_AM::rrx) |
4145 |
.Case("rrx", ARM_AM::rrx) |
| 4146 |
.Default(ARM_AM::no_shift); |
4146 |
.Default(ARM_AM::no_shift); |
| 4147 |
|
4147 |
|
| 4148 |
if (ShiftTy == ARM_AM::no_shift) |
4148 |
if (ShiftTy == ARM_AM::no_shift) |
| 4149 |
return 1; |
4149 |
return 1; |
| 4150 |
|
4150 |
|
| 4151 |
Parser.Lex(); // Eat the operator. |
4151 |
Parser.Lex(); // Eat the operator. |
| 4152 |
|
4152 |
|
| 4153 |
// The source register for the shift has already been added to the |
4153 |
// The source register for the shift has already been added to the |
| 4154 |
// operand list, so we need to pop it off and combine it into the shifted |
4154 |
// operand list, so we need to pop it off and combine it into the shifted |
| 4155 |
// register operand instead. |
4155 |
// register operand instead. |
| 4156 |
std::unique_ptr PrevOp( |
4156 |
std::unique_ptr PrevOp( |
| 4157 |
(ARMOperand *)Operands.pop_back_val().release()); |
4157 |
(ARMOperand *)Operands.pop_back_val().release()); |
| 4158 |
if (!PrevOp->isReg()) |
4158 |
if (!PrevOp->isReg()) |
| 4159 |
return Error(PrevOp->getStartLoc(), "shift must be of a register"); |
4159 |
return Error(PrevOp->getStartLoc(), "shift must be of a register"); |
| 4160 |
int SrcReg = PrevOp->getReg(); |
4160 |
int SrcReg = PrevOp->getReg(); |
| 4161 |
|
4161 |
|
| 4162 |
SMLoc EndLoc; |
4162 |
SMLoc EndLoc; |
| 4163 |
int64_t Imm = 0; |
4163 |
int64_t Imm = 0; |
| 4164 |
int ShiftReg = 0; |
4164 |
int ShiftReg = 0; |
| 4165 |
if (ShiftTy == ARM_AM::rrx) { |
4165 |
if (ShiftTy == ARM_AM::rrx) { |
| 4166 |
// RRX Doesn't have an explicit shift amount. The encoder expects |
4166 |
// RRX Doesn't have an explicit shift amount. The encoder expects |
| 4167 |
// the shift register to be the same as the source register. Seems odd, |
4167 |
// the shift register to be the same as the source register. Seems odd, |
| 4168 |
// but OK. |
4168 |
// but OK. |
| 4169 |
ShiftReg = SrcReg; |
4169 |
ShiftReg = SrcReg; |
| 4170 |
} else { |
4170 |
} else { |
| 4171 |
// Figure out if this is shifted by a constant or a register (for non-RRX). |
4171 |
// Figure out if this is shifted by a constant or a register (for non-RRX). |
| 4172 |
if (Parser.getTok().is(AsmToken::Hash) || |
4172 |
if (Parser.getTok().is(AsmToken::Hash) || |
| 4173 |
Parser.getTok().is(AsmToken::Dollar)) { |
4173 |
Parser.getTok().is(AsmToken::Dollar)) { |
| 4174 |
Parser.Lex(); // Eat hash. |
4174 |
Parser.Lex(); // Eat hash. |
| 4175 |
SMLoc ImmLoc = Parser.getTok().getLoc(); |
4175 |
SMLoc ImmLoc = Parser.getTok().getLoc(); |
| 4176 |
const MCExpr *ShiftExpr = nullptr; |
4176 |
const MCExpr *ShiftExpr = nullptr; |
| 4177 |
if (getParser().parseExpression(ShiftExpr, EndLoc)) { |
4177 |
if (getParser().parseExpression(ShiftExpr, EndLoc)) { |
| 4178 |
Error(ImmLoc, "invalid immediate shift value"); |
4178 |
Error(ImmLoc, "invalid immediate shift value"); |
| 4179 |
return -1; |
4179 |
return -1; |
| 4180 |
} |
4180 |
} |
| 4181 |
// The expression must be evaluatable as an immediate. |
4181 |
// The expression must be evaluatable as an immediate. |
| 4182 |
const MCConstantExpr *CE = dyn_cast(ShiftExpr); |
4182 |
const MCConstantExpr *CE = dyn_cast(ShiftExpr); |
| 4183 |
if (!CE) { |
4183 |
if (!CE) { |
| 4184 |
Error(ImmLoc, "invalid immediate shift value"); |
4184 |
Error(ImmLoc, "invalid immediate shift value"); |
| 4185 |
return -1; |
4185 |
return -1; |
| 4186 |
} |
4186 |
} |
| 4187 |
// Range check the immediate. |
4187 |
// Range check the immediate. |
| 4188 |
// lsl, ror: 0 <= imm <= 31 |
4188 |
// lsl, ror: 0 <= imm <= 31 |
| 4189 |
// lsr, asr: 0 <= imm <= 32 |
4189 |
// lsr, asr: 0 <= imm <= 32 |
| 4190 |
Imm = CE->getValue(); |
4190 |
Imm = CE->getValue(); |
| 4191 |
if (Imm < 0 || |
4191 |
if (Imm < 0 || |
| 4192 |
((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) || |
4192 |
((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) || |
| 4193 |
((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) { |
4193 |
((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) { |
| 4194 |
Error(ImmLoc, "immediate shift value out of range"); |
4194 |
Error(ImmLoc, "immediate shift value out of range"); |
| 4195 |
return -1; |
4195 |
return -1; |
| 4196 |
} |
4196 |
} |
| 4197 |
// shift by zero is a nop. Always send it through as lsl. |
4197 |
// shift by zero is a nop. Always send it through as lsl. |
| 4198 |
// ('as' compatibility) |
4198 |
// ('as' compatibility) |
| 4199 |
if (Imm == 0) |
4199 |
if (Imm == 0) |
| 4200 |
ShiftTy = ARM_AM::lsl; |
4200 |
ShiftTy = ARM_AM::lsl; |
| 4201 |
} else if (Parser.getTok().is(AsmToken::Identifier)) { |
4201 |
} else if (Parser.getTok().is(AsmToken::Identifier)) { |
| 4202 |
SMLoc L = Parser.getTok().getLoc(); |
4202 |
SMLoc L = Parser.getTok().getLoc(); |
| 4203 |
EndLoc = Parser.getTok().getEndLoc(); |
4203 |
EndLoc = Parser.getTok().getEndLoc(); |
| 4204 |
ShiftReg = tryParseRegister(); |
4204 |
ShiftReg = tryParseRegister(); |
| 4205 |
if (ShiftReg == -1) { |
4205 |
if (ShiftReg == -1) { |
| 4206 |
Error(L, "expected immediate or register in shift operand"); |
4206 |
Error(L, "expected immediate or register in shift operand"); |
| 4207 |
return -1; |
4207 |
return -1; |
| 4208 |
} |
4208 |
} |
| 4209 |
} else { |
4209 |
} else { |
| 4210 |
Error(Parser.getTok().getLoc(), |
4210 |
Error(Parser.getTok().getLoc(), |
| 4211 |
"expected immediate or register in shift operand"); |
4211 |
"expected immediate or register in shift operand"); |
| 4212 |
return -1; |
4212 |
return -1; |
| 4213 |
} |
4213 |
} |
| 4214 |
} |
4214 |
} |
| 4215 |
|
4215 |
|
| 4216 |
if (ShiftReg && ShiftTy != ARM_AM::rrx) |
4216 |
if (ShiftReg && ShiftTy != ARM_AM::rrx) |
| 4217 |
Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg, |
4217 |
Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg, |
| 4218 |
ShiftReg, Imm, |
4218 |
ShiftReg, Imm, |
| 4219 |
S, EndLoc)); |
4219 |
S, EndLoc)); |
| 4220 |
else |
4220 |
else |
| 4221 |
Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm, |
4221 |
Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm, |
| 4222 |
S, EndLoc)); |
4222 |
S, EndLoc)); |
| 4223 |
|
4223 |
|
| 4224 |
return 0; |
4224 |
return 0; |
| 4225 |
} |
4225 |
} |
| 4226 |
|
4226 |
|
| 4227 |
/// Try to parse a register name. The token must be an Identifier when called. |
4227 |
/// Try to parse a register name. The token must be an Identifier when called. |
| 4228 |
/// If it's a register, an AsmOperand is created. Another AsmOperand is created |
4228 |
/// If it's a register, an AsmOperand is created. Another AsmOperand is created |
| 4229 |
/// if there is a "writeback". 'true' if it's not a register. |
4229 |
/// if there is a "writeback". 'true' if it's not a register. |
| 4230 |
/// |
4230 |
/// |
| 4231 |
/// TODO this is likely to change to allow different register types and or to |
4231 |
/// TODO this is likely to change to allow different register types and or to |
| 4232 |
/// parse for a specific register type. |
4232 |
/// parse for a specific register type. |
| 4233 |
bool ARMAsmParser::tryParseRegisterWithWriteBack(OperandVector &Operands) { |
4233 |
bool ARMAsmParser::tryParseRegisterWithWriteBack(OperandVector &Operands) { |
| 4234 |
MCAsmParser &Parser = getParser(); |
4234 |
MCAsmParser &Parser = getParser(); |
| 4235 |
SMLoc RegStartLoc = Parser.getTok().getLoc(); |
4235 |
SMLoc RegStartLoc = Parser.getTok().getLoc(); |
| 4236 |
SMLoc RegEndLoc = Parser.getTok().getEndLoc(); |
4236 |
SMLoc RegEndLoc = Parser.getTok().getEndLoc(); |
| 4237 |
int RegNo = tryParseRegister(); |
4237 |
int RegNo = tryParseRegister(); |
| 4238 |
if (RegNo == -1) |
4238 |
if (RegNo == -1) |
| 4239 |
return true; |
4239 |
return true; |
| 4240 |
|
4240 |
|
| 4241 |
Operands.push_back(ARMOperand::CreateReg(RegNo, RegStartLoc, RegEndLoc)); |
4241 |
Operands.push_back(ARMOperand::CreateReg(RegNo, RegStartLoc, RegEndLoc)); |
| 4242 |
|
4242 |
|
| 4243 |
const AsmToken &ExclaimTok = Parser.getTok(); |
4243 |
const AsmToken &ExclaimTok = Parser.getTok(); |
| 4244 |
if (ExclaimTok.is(AsmToken::Exclaim)) { |
4244 |
if (ExclaimTok.is(AsmToken::Exclaim)) { |
| 4245 |
Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(), |
4245 |
Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(), |
| 4246 |
ExclaimTok.getLoc())); |
4246 |
ExclaimTok.getLoc())); |
| 4247 |
Parser.Lex(); // Eat exclaim token |
4247 |
Parser.Lex(); // Eat exclaim token |
| 4248 |
return false; |
4248 |
return false; |
| 4249 |
} |
4249 |
} |
| 4250 |
|
4250 |
|
| 4251 |
// Also check for an index operand. This is only legal for vector registers, |
4251 |
// Also check for an index operand. This is only legal for vector registers, |
| 4252 |
// but that'll get caught OK in operand matching, so we don't need to |
4252 |
// but that'll get caught OK in operand matching, so we don't need to |
| 4253 |
// explicitly filter everything else out here. |
4253 |
// explicitly filter everything else out here. |
| 4254 |
if (Parser.getTok().is(AsmToken::LBrac)) { |
4254 |
if (Parser.getTok().is(AsmToken::LBrac)) { |
| 4255 |
SMLoc SIdx = Parser.getTok().getLoc(); |
4255 |
SMLoc SIdx = Parser.getTok().getLoc(); |
| 4256 |
Parser.Lex(); // Eat left bracket token. |
4256 |
Parser.Lex(); // Eat left bracket token. |
| 4257 |
|
4257 |
|
| 4258 |
const MCExpr *ImmVal; |
4258 |
const MCExpr *ImmVal; |
| 4259 |
if (getParser().parseExpression(ImmVal)) |
4259 |
if (getParser().parseExpression(ImmVal)) |
| 4260 |
return true; |
4260 |
return true; |
| 4261 |
const MCConstantExpr *MCE = dyn_cast(ImmVal); |
4261 |
const MCConstantExpr *MCE = dyn_cast(ImmVal); |
| 4262 |
if (!MCE) |
4262 |
if (!MCE) |
| 4263 |
return TokError("immediate value expected for vector index"); |
4263 |
return TokError("immediate value expected for vector index"); |
| 4264 |
|
4264 |
|
| 4265 |
if (Parser.getTok().isNot(AsmToken::RBrac)) |
4265 |
if (Parser.getTok().isNot(AsmToken::RBrac)) |
| 4266 |
return Error(Parser.getTok().getLoc(), "']' expected"); |
4266 |
return Error(Parser.getTok().getLoc(), "']' expected"); |
| 4267 |
|
4267 |
|
| 4268 |
SMLoc E = Parser.getTok().getEndLoc(); |
4268 |
SMLoc E = Parser.getTok().getEndLoc(); |
| 4269 |
Parser.Lex(); // Eat right bracket token. |
4269 |
Parser.Lex(); // Eat right bracket token. |
| 4270 |
|
4270 |
|
| 4271 |
Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(), |
4271 |
Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(), |
| 4272 |
SIdx, E, |
4272 |
SIdx, E, |
| 4273 |
getContext())); |
4273 |
getContext())); |
| 4274 |
} |
4274 |
} |
| 4275 |
|
4275 |
|
| 4276 |
return false; |
4276 |
return false; |
| 4277 |
} |
4277 |
} |
| 4278 |
|
4278 |
|
| 4279 |
/// MatchCoprocessorOperandName - Try to parse an coprocessor related |
4279 |
/// MatchCoprocessorOperandName - Try to parse an coprocessor related |
| 4280 |
/// instruction with a symbolic operand name. |
4280 |
/// instruction with a symbolic operand name. |
| 4281 |
/// We accept "crN" syntax for GAS compatibility. |
4281 |
/// We accept "crN" syntax for GAS compatibility. |
| 4282 |
/// ::= |
4282 |
/// ::= |
| 4283 |
/// If CoprocOp is 'c', then: |
4283 |
/// If CoprocOp is 'c', then: |
| 4284 |
/// ::= c | cr |
4284 |
/// ::= c | cr |
| 4285 |
/// If CoprocOp is 'p', then : |
4285 |
/// If CoprocOp is 'p', then : |
| 4286 |
/// ::= p |
4286 |
/// ::= p |
| 4287 |
/// ::= integer in range [0, 15] |
4287 |
/// ::= integer in range [0, 15] |
| 4288 |
static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) { |
4288 |
static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) { |
| 4289 |
// Use the same layout as the tablegen'erated register name matcher. Ugly, |
4289 |
// Use the same layout as the tablegen'erated register name matcher. Ugly, |
| 4290 |
// but efficient. |
4290 |
// but efficient. |
| 4291 |
if (Name.size() < 2 || Name[0] != CoprocOp) |
4291 |
if (Name.size() < 2 || Name[0] != CoprocOp) |
| 4292 |
return -1; |
4292 |
return -1; |
| 4293 |
Name = (Name[1] == 'r') ? Name.drop_front(2) : Name.drop_front(); |
4293 |
Name = (Name[1] == 'r') ? Name.drop_front(2) : Name.drop_front(); |
| 4294 |
|
4294 |
|
| 4295 |
switch (Name.size()) { |
4295 |
switch (Name.size()) { |
| 4296 |
default: return -1; |
4296 |
default: return -1; |
| 4297 |
case 1: |
4297 |
case 1: |
| 4298 |
switch (Name[0]) { |
4298 |
switch (Name[0]) { |
| 4299 |
default: return -1; |
4299 |
default: return -1; |
| 4300 |
case '0': return 0; |
4300 |
case '0': return 0; |
| 4301 |
case '1': return 1; |
4301 |
case '1': return 1; |
| 4302 |
case '2': return 2; |
4302 |
case '2': return 2; |
| 4303 |
case '3': return 3; |
4303 |
case '3': return 3; |
| 4304 |
case '4': return 4; |
4304 |
case '4': return 4; |
| 4305 |
case '5': return 5; |
4305 |
case '5': return 5; |
| 4306 |
case '6': return 6; |
4306 |
case '6': return 6; |
| 4307 |
case '7': return 7; |
4307 |
case '7': return 7; |
| 4308 |
case '8': return 8; |
4308 |
case '8': return 8; |
| 4309 |
case '9': return 9; |
4309 |
case '9': return 9; |
| 4310 |
} |
4310 |
} |
| 4311 |
case 2: |
4311 |
case 2: |
| 4312 |
if (Name[0] != '1') |
4312 |
if (Name[0] != '1') |
| 4313 |
return -1; |
4313 |
return -1; |
| 4314 |
switch (Name[1]) { |
4314 |
switch (Name[1]) { |
| 4315 |
default: return -1; |
4315 |
default: return -1; |
| 4316 |
// CP10 and CP11 are VFP/NEON and so vector instructions should be used. |
4316 |
// CP10 and CP11 are VFP/NEON and so vector instructions should be used. |
| 4317 |
// However, old cores (v5/v6) did use them in that way. |
4317 |
// However, old cores (v5/v6) did use them in that way. |
| 4318 |
case '0': return 10; |
4318 |
case '0': return 10; |
| 4319 |
case '1': return 11; |
4319 |
case '1': return 11; |
| 4320 |
case '2': return 12; |
4320 |
case '2': return 12; |
| 4321 |
case '3': return 13; |
4321 |
case '3': return 13; |
| 4322 |
case '4': return 14; |
4322 |
case '4': return 14; |
| 4323 |
case '5': return 15; |
4323 |
case '5': return 15; |
| 4324 |
} |
4324 |
} |
| 4325 |
} |
4325 |
} |
| 4326 |
} |
4326 |
} |
| 4327 |
|
4327 |
|
| 4328 |
/// parseITCondCode - Try to parse a condition code for an IT instruction. |
4328 |
/// parseITCondCode - Try to parse a condition code for an IT instruction. |
| 4329 |
ParseStatus ARMAsmParser::parseITCondCode(OperandVector &Operands) { |
4329 |
ParseStatus ARMAsmParser::parseITCondCode(OperandVector &Operands) { |
| 4330 |
MCAsmParser &Parser = getParser(); |
4330 |
MCAsmParser &Parser = getParser(); |
| 4331 |
SMLoc S = Parser.getTok().getLoc(); |
4331 |
SMLoc S = Parser.getTok().getLoc(); |
| 4332 |
const AsmToken &Tok = Parser.getTok(); |
4332 |
const AsmToken &Tok = Parser.getTok(); |
| 4333 |
if (!Tok.is(AsmToken::Identifier)) |
4333 |
if (!Tok.is(AsmToken::Identifier)) |
| 4334 |
return ParseStatus::NoMatch; |
4334 |
return ParseStatus::NoMatch; |
| 4335 |
unsigned CC = ARMCondCodeFromString(Tok.getString()); |
4335 |
unsigned CC = ARMCondCodeFromString(Tok.getString()); |
| 4336 |
if (CC == ~0U) |
4336 |
if (CC == ~0U) |
| 4337 |
return ParseStatus::NoMatch; |
4337 |
return ParseStatus::NoMatch; |
| 4338 |
Parser.Lex(); // Eat the token. |
4338 |
Parser.Lex(); // Eat the token. |
| 4339 |
|
4339 |
|
| 4340 |
Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S)); |
4340 |
Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S)); |
| 4341 |
|
4341 |
|
| 4342 |
return ParseStatus::Success; |
4342 |
return ParseStatus::Success; |
| 4343 |
} |
4343 |
} |
| 4344 |
|
4344 |
|
| 4345 |
/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The |
4345 |
/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The |
| 4346 |
/// token must be an Identifier when called, and if it is a coprocessor |
4346 |
/// token must be an Identifier when called, and if it is a coprocessor |
| 4347 |
/// number, the token is eaten and the operand is added to the operand list. |
4347 |
/// number, the token is eaten and the operand is added to the operand list. |
| 4348 |
ParseStatus ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) { |
4348 |
ParseStatus ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) { |
| 4349 |
MCAsmParser &Parser = getParser(); |
4349 |
MCAsmParser &Parser = getParser(); |
| 4350 |
SMLoc S = Parser.getTok().getLoc(); |
4350 |
SMLoc S = Parser.getTok().getLoc(); |
| 4351 |
const AsmToken &Tok = Parser.getTok(); |
4351 |
const AsmToken &Tok = Parser.getTok(); |
| 4352 |
if (Tok.isNot(AsmToken::Identifier)) |
4352 |
if (Tok.isNot(AsmToken::Identifier)) |
| 4353 |
return ParseStatus::NoMatch; |
4353 |
return ParseStatus::NoMatch; |
| 4354 |
|
4354 |
|
| 4355 |
int Num = MatchCoprocessorOperandName(Tok.getString().lower(), 'p'); |
4355 |
int Num = MatchCoprocessorOperandName(Tok.getString().lower(), 'p'); |
| 4356 |
if (Num == -1) |
4356 |
if (Num == -1) |
| 4357 |
return ParseStatus::NoMatch; |
4357 |
return ParseStatus::NoMatch; |
| 4358 |
if (!isValidCoprocessorNumber(Num, getSTI().getFeatureBits())) |
4358 |
if (!isValidCoprocessorNumber(Num, getSTI().getFeatureBits())) |
| 4359 |
return ParseStatus::NoMatch; |
4359 |
return ParseStatus::NoMatch; |
| 4360 |
|
4360 |
|
| 4361 |
Parser.Lex(); // Eat identifier token. |
4361 |
Parser.Lex(); // Eat identifier token. |
| 4362 |
Operands.push_back(ARMOperand::CreateCoprocNum(Num, S)); |
4362 |
Operands.push_back(ARMOperand::CreateCoprocNum(Num, S)); |
| 4363 |
return ParseStatus::Success; |
4363 |
return ParseStatus::Success; |
| 4364 |
} |
4364 |
} |
| 4365 |
|
4365 |
|
| 4366 |
/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The |
4366 |
/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The |
| 4367 |
/// token must be an Identifier when called, and if it is a coprocessor |
4367 |
/// token must be an Identifier when called, and if it is a coprocessor |
| 4368 |
/// number, the token is eaten and the operand is added to the operand list. |
4368 |
/// number, the token is eaten and the operand is added to the operand list. |
| 4369 |
ParseStatus ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) { |
4369 |
ParseStatus ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) { |
| 4370 |
MCAsmParser &Parser = getParser(); |
4370 |
MCAsmParser &Parser = getParser(); |
| 4371 |
SMLoc S = Parser.getTok().getLoc(); |
4371 |
SMLoc S = Parser.getTok().getLoc(); |
| 4372 |
const AsmToken &Tok = Parser.getTok(); |
4372 |
const AsmToken &Tok = Parser.getTok(); |
| 4373 |
if (Tok.isNot(AsmToken::Identifier)) |
4373 |
if (Tok.isNot(AsmToken::Identifier)) |
| 4374 |
return ParseStatus::NoMatch; |
4374 |
return ParseStatus::NoMatch; |
| 4375 |
|
4375 |
|
| 4376 |
int Reg = MatchCoprocessorOperandName(Tok.getString().lower(), 'c'); |
4376 |
int Reg = MatchCoprocessorOperandName(Tok.getString().lower(), 'c'); |
| 4377 |
if (Reg == -1) |
4377 |
if (Reg == -1) |
| 4378 |
return ParseStatus::NoMatch; |
4378 |
return ParseStatus::NoMatch; |
| 4379 |
|
4379 |
|
| 4380 |
Parser.Lex(); // Eat identifier token. |
4380 |
Parser.Lex(); // Eat identifier token. |
| 4381 |
Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S)); |
4381 |
Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S)); |
| 4382 |
return ParseStatus::Success; |
4382 |
return ParseStatus::Success; |
| 4383 |
} |
4383 |
} |
| 4384 |
|
4384 |
|
| 4385 |
/// parseCoprocOptionOperand - Try to parse an coprocessor option operand. |
4385 |
/// parseCoprocOptionOperand - Try to parse an coprocessor option operand. |
| 4386 |
/// coproc_option : '{' imm0_255 '}' |
4386 |
/// coproc_option : '{' imm0_255 '}' |
| 4387 |
ParseStatus ARMAsmParser::parseCoprocOptionOperand(OperandVector &Operands) { |
4387 |
ParseStatus ARMAsmParser::parseCoprocOptionOperand(OperandVector &Operands) { |
| 4388 |
MCAsmParser &Parser = getParser(); |
4388 |
MCAsmParser &Parser = getParser(); |
| 4389 |
SMLoc S = Parser.getTok().getLoc(); |
4389 |
SMLoc S = Parser.getTok().getLoc(); |
| 4390 |
|
4390 |
|
| 4391 |
// If this isn't a '{', this isn't a coprocessor immediate operand. |
4391 |
// If this isn't a '{', this isn't a coprocessor immediate operand. |
| 4392 |
if (Parser.getTok().isNot(AsmToken::LCurly)) |
4392 |
if (Parser.getTok().isNot(AsmToken::LCurly)) |
| 4393 |
return ParseStatus::NoMatch; |
4393 |
return ParseStatus::NoMatch; |
| 4394 |
Parser.Lex(); // Eat the '{' |
4394 |
Parser.Lex(); // Eat the '{' |
| 4395 |
|
4395 |
|
| 4396 |
const MCExpr *Expr; |
4396 |
const MCExpr *Expr; |
| 4397 |
SMLoc Loc = Parser.getTok().getLoc(); |
4397 |
SMLoc Loc = Parser.getTok().getLoc(); |
| 4398 |
if (getParser().parseExpression(Expr)) |
4398 |
if (getParser().parseExpression(Expr)) |
| 4399 |
return Error(Loc, "illegal expression"); |
4399 |
return Error(Loc, "illegal expression"); |
| 4400 |
const MCConstantExpr *CE = dyn_cast(Expr); |
4400 |
const MCConstantExpr *CE = dyn_cast(Expr); |
| 4401 |
if (!CE || CE->getValue() < 0 || CE->getValue() > 255) |
4401 |
if (!CE || CE->getValue() < 0 || CE->getValue() > 255) |
| 4402 |
return Error(Loc, |
4402 |
return Error(Loc, |
| 4403 |
"coprocessor option must be an immediate in range [0, 255]"); |
4403 |
"coprocessor option must be an immediate in range [0, 255]"); |
| 4404 |
int Val = CE->getValue(); |
4404 |
int Val = CE->getValue(); |
| 4405 |
|
4405 |
|
| 4406 |
// Check for and consume the closing '}' |
4406 |
// Check for and consume the closing '}' |
| 4407 |
if (Parser.getTok().isNot(AsmToken::RCurly)) |
4407 |
if (Parser.getTok().isNot(AsmToken::RCurly)) |
| 4408 |
return ParseStatus::Failure; |
4408 |
return ParseStatus::Failure; |
| 4409 |
SMLoc E = Parser.getTok().getEndLoc(); |
4409 |
SMLoc E = Parser.getTok().getEndLoc(); |
| 4410 |
Parser.Lex(); // Eat the '}' |
4410 |
Parser.Lex(); // Eat the '}' |
| 4411 |
|
4411 |
|
| 4412 |
Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E)); |
4412 |
Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E)); |
| 4413 |
return ParseStatus::Success; |
4413 |
return ParseStatus::Success; |
| 4414 |
} |
4414 |
} |
| 4415 |
|
4415 |
|
| 4416 |
// For register list parsing, we need to map from raw GPR register numbering |
4416 |
// For register list parsing, we need to map from raw GPR register numbering |
| 4417 |
// to the enumeration values. The enumeration values aren't sorted by |
4417 |
// to the enumeration values. The enumeration values aren't sorted by |
| 4418 |
// register number due to our using "sp", "lr" and "pc" as canonical names. |
4418 |
// register number due to our using "sp", "lr" and "pc" as canonical names. |
| 4419 |
static unsigned getNextRegister(unsigned Reg) { |
4419 |
static unsigned getNextRegister(unsigned Reg) { |
| 4420 |
// If this is a GPR, we need to do it manually, otherwise we can rely |
4420 |
// If this is a GPR, we need to do it manually, otherwise we can rely |
| 4421 |
// on the sort ordering of the enumeration since the other reg-classes |
4421 |
// on the sort ordering of the enumeration since the other reg-classes |
| 4422 |
// are sane. |
4422 |
// are sane. |
| 4423 |
if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) |
4423 |
if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) |
| 4424 |
return Reg + 1; |
4424 |
return Reg + 1; |
| 4425 |
switch(Reg) { |
4425 |
switch(Reg) { |
| 4426 |
default: llvm_unreachable("Invalid GPR number!"); |
4426 |
default: llvm_unreachable("Invalid GPR number!"); |
| 4427 |
case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2; |
4427 |
case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2; |
| 4428 |
case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4; |
4428 |
case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4; |
| 4429 |
case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6; |
4429 |
case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6; |
| 4430 |
case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8; |
4430 |
case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8; |
| 4431 |
case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10; |
4431 |
case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10; |
| 4432 |
case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12; |
4432 |
case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12; |
| 4433 |
case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR; |
4433 |
case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR; |
| 4434 |
case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0; |
4434 |
case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0; |
| 4435 |
} |
4435 |
} |
| 4436 |
} |
4436 |
} |
| 4437 |
|
4437 |
|
| 4438 |
// Insert an pair in an ordered vector. Return true on |
4438 |
// Insert an pair in an ordered vector. Return true on |
| 4439 |
// success, or false, if duplicate encoding found. |
4439 |
// success, or false, if duplicate encoding found. |
| 4440 |
static bool |
4440 |
static bool |
| 4441 |
insertNoDuplicates(SmallVectorImpl> &Regs, |
4441 |
insertNoDuplicates(SmallVectorImpl> &Regs, |
| 4442 |
unsigned Enc, unsigned Reg) { |
4442 |
unsigned Enc, unsigned Reg) { |
| 4443 |
Regs.emplace_back(Enc, Reg); |
4443 |
Regs.emplace_back(Enc, Reg); |
| 4444 |
for (auto I = Regs.rbegin(), J = I + 1, E = Regs.rend(); J != E; ++I, ++J) { |
4444 |
for (auto I = Regs.rbegin(), J = I + 1, E = Regs.rend(); J != E; ++I, ++J) { |
| 4445 |
if (J->first == Enc) { |
4445 |
if (J->first == Enc) { |
| 4446 |
Regs.erase(J.base()); |
4446 |
Regs.erase(J.base()); |
| 4447 |
return false; |
4447 |
return false; |
| 4448 |
} |
4448 |
} |
| 4449 |
if (J->first < Enc) |
4449 |
if (J->first < Enc) |
| 4450 |
break; |
4450 |
break; |
| 4451 |
std::swap(*I, *J); |
4451 |
std::swap(*I, *J); |
| 4452 |
} |
4452 |
} |
| 4453 |
return true; |
4453 |
return true; |
| 4454 |
} |
4454 |
} |
| 4455 |
|
4455 |
|
| 4456 |
/// Parse a register list. |
4456 |
/// Parse a register list. |
| 4457 |
bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder, |
4457 |
bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder, |
| 4458 |
bool AllowRAAC) { |
4458 |
bool AllowRAAC) { |
| 4459 |
MCAsmParser &Parser = getParser(); |
4459 |
MCAsmParser &Parser = getParser(); |
| 4460 |
if (Parser.getTok().isNot(AsmToken::LCurly)) |
4460 |
if (Parser.getTok().isNot(AsmToken::LCurly)) |
| 4461 |
return TokError("Token is not a Left Curly Brace"); |
4461 |
return TokError("Token is not a Left Curly Brace"); |
| 4462 |
SMLoc S = Parser.getTok().getLoc(); |
4462 |
SMLoc S = Parser.getTok().getLoc(); |
| 4463 |
Parser.Lex(); // Eat '{' token. |
4463 |
Parser.Lex(); // Eat '{' token. |
| 4464 |
SMLoc RegLoc = Parser.getTok().getLoc(); |
4464 |
SMLoc RegLoc = Parser.getTok().getLoc(); |
| 4465 |
|
4465 |
|
| 4466 |
// Check the first register in the list to see what register class |
4466 |
// Check the first register in the list to see what register class |
| 4467 |
// this is a list of. |
4467 |
// this is a list of. |
| 4468 |
int Reg = tryParseRegister(); |
4468 |
int Reg = tryParseRegister(); |
| 4469 |
if (Reg == -1) |
4469 |
if (Reg == -1) |
| 4470 |
return Error(RegLoc, "register expected"); |
4470 |
return Error(RegLoc, "register expected"); |
| 4471 |
if (!AllowRAAC && Reg == ARM::RA_AUTH_CODE) |
4471 |
if (!AllowRAAC && Reg == ARM::RA_AUTH_CODE) |
| 4472 |
return Error(RegLoc, "pseudo-register not allowed"); |
4472 |
return Error(RegLoc, "pseudo-register not allowed"); |
| 4473 |
// The reglist instructions have at most 16 registers, so reserve |
4473 |
// The reglist instructions have at most 16 registers, so reserve |
| 4474 |
// space for that many. |
4474 |
// space for that many. |
| 4475 |
int EReg = 0; |
4475 |
int EReg = 0; |
| 4476 |
SmallVector, 16> Registers; |
4476 |
SmallVector, 16> Registers; |
| 4477 |
|
4477 |
|
| 4478 |
// Allow Q regs and just interpret them as the two D sub-registers. |
4478 |
// Allow Q regs and just interpret them as the two D sub-registers. |
| 4479 |
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { |
4479 |
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { |
| 4480 |
Reg = getDRegFromQReg(Reg); |
4480 |
Reg = getDRegFromQReg(Reg); |
| 4481 |
EReg = MRI->getEncodingValue(Reg); |
4481 |
EReg = MRI->getEncodingValue(Reg); |
| 4482 |
Registers.emplace_back(EReg, Reg); |
4482 |
Registers.emplace_back(EReg, Reg); |
| 4483 |
++Reg; |
4483 |
++Reg; |
| 4484 |
} |
4484 |
} |
| 4485 |
const MCRegisterClass *RC; |
4485 |
const MCRegisterClass *RC; |
| 4486 |
if (Reg == ARM::RA_AUTH_CODE || |
4486 |
if (Reg == ARM::RA_AUTH_CODE || |
| 4487 |
ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) |
4487 |
ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) |
| 4488 |
RC = &ARMMCRegisterClasses[ARM::GPRRegClassID]; |
4488 |
RC = &ARMMCRegisterClasses[ARM::GPRRegClassID]; |
| 4489 |
else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) |
4489 |
else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) |
| 4490 |
RC = &ARMMCRegisterClasses[ARM::DPRRegClassID]; |
4490 |
RC = &ARMMCRegisterClasses[ARM::DPRRegClassID]; |
| 4491 |
else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg)) |
4491 |
else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg)) |
| 4492 |
RC = &ARMMCRegisterClasses[ARM::SPRRegClassID]; |
4492 |
RC = &ARMMCRegisterClasses[ARM::SPRRegClassID]; |
| 4493 |
else if (ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) |
4493 |
else if (ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) |
| 4494 |
RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID]; |
4494 |
RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID]; |
| 4495 |
else |
4495 |
else |
| 4496 |
return Error(RegLoc, "invalid register in register list"); |
4496 |
return Error(RegLoc, "invalid register in register list"); |
| 4497 |
|
4497 |
|
| 4498 |
// Store the register. |
4498 |
// Store the register. |
| 4499 |
EReg = MRI->getEncodingValue(Reg); |
4499 |
EReg = MRI->getEncodingValue(Reg); |
| 4500 |
Registers.emplace_back(EReg, Reg); |
4500 |
Registers.emplace_back(EReg, Reg); |
| 4501 |
|
4501 |
|
| 4502 |
// This starts immediately after the first register token in the list, |
4502 |
// This starts immediately after the first register token in the list, |
| 4503 |
// so we can see either a comma or a minus (range separator) as a legal |
4503 |
// so we can see either a comma or a minus (range separator) as a legal |
| 4504 |
// next token. |
4504 |
// next token. |
| 4505 |
while (Parser.getTok().is(AsmToken::Comma) || |
4505 |
while (Parser.getTok().is(AsmToken::Comma) || |
| 4506 |
Parser.getTok().is(AsmToken::Minus)) { |
4506 |
Parser.getTok().is(AsmToken::Minus)) { |
| 4507 |
if (Parser.getTok().is(AsmToken::Minus)) { |
4507 |
if (Parser.getTok().is(AsmToken::Minus)) { |
| 4508 |
if (Reg == ARM::RA_AUTH_CODE) |
4508 |
if (Reg == ARM::RA_AUTH_CODE) |
| 4509 |
return Error(RegLoc, "pseudo-register not allowed"); |
4509 |
return Error(RegLoc, "pseudo-register not allowed"); |
| 4510 |
Parser.Lex(); // Eat the minus. |
4510 |
Parser.Lex(); // Eat the minus. |
| 4511 |
SMLoc AfterMinusLoc = Parser.getTok().getLoc(); |
4511 |
SMLoc AfterMinusLoc = Parser.getTok().getLoc(); |
| 4512 |
int EndReg = tryParseRegister(); |
4512 |
int EndReg = tryParseRegister(); |
| 4513 |
if (EndReg == -1) |
4513 |
if (EndReg == -1) |
| 4514 |
return Error(AfterMinusLoc, "register expected"); |
4514 |
return Error(AfterMinusLoc, "register expected"); |
| 4515 |
if (EndReg == ARM::RA_AUTH_CODE) |
4515 |
if (EndReg == ARM::RA_AUTH_CODE) |
| 4516 |
return Error(AfterMinusLoc, "pseudo-register not allowed"); |
4516 |
return Error(AfterMinusLoc, "pseudo-register not allowed"); |
| 4517 |
// Allow Q regs and just interpret them as the two D sub-registers. |
4517 |
// Allow Q regs and just interpret them as the two D sub-registers. |
| 4518 |
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg)) |
4518 |
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg)) |
| 4519 |
EndReg = getDRegFromQReg(EndReg) + 1; |
4519 |
EndReg = getDRegFromQReg(EndReg) + 1; |
| 4520 |
// If the register is the same as the start reg, there's nothing |
4520 |
// If the register is the same as the start reg, there's nothing |
| 4521 |
// more to do. |
4521 |
// more to do. |
| 4522 |
if (Reg == EndReg) |
4522 |
if (Reg == EndReg) |
| 4523 |
continue; |
4523 |
continue; |
| 4524 |
// The register must be in the same register class as the first. |
4524 |
// The register must be in the same register class as the first. |
| 4525 |
if (!RC->contains(Reg)) |
4525 |
if (!RC->contains(Reg)) |
| 4526 |
return Error(AfterMinusLoc, "invalid register in register list"); |
4526 |
return Error(AfterMinusLoc, "invalid register in register list"); |
| 4527 |
// Ranges must go from low to high. |
4527 |
// Ranges must go from low to high. |
| 4528 |
if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg)) |
4528 |
if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg)) |
| 4529 |
return Error(AfterMinusLoc, "bad range in register list"); |
4529 |
return Error(AfterMinusLoc, "bad range in register list"); |
| 4530 |
|
4530 |
|
| 4531 |
// Add all the registers in the range to the register list. |
4531 |
// Add all the registers in the range to the register list. |
| 4532 |
while (Reg != EndReg) { |
4532 |
while (Reg != EndReg) { |
| 4533 |
Reg = getNextRegister(Reg); |
4533 |
Reg = getNextRegister(Reg); |
| 4534 |
EReg = MRI->getEncodingValue(Reg); |
4534 |
EReg = MRI->getEncodingValue(Reg); |
| 4535 |
if (!insertNoDuplicates(Registers, EReg, Reg)) { |
4535 |
if (!insertNoDuplicates(Registers, EReg, Reg)) { |
| 4536 |
Warning(AfterMinusLoc, StringRef("duplicated register (") + |
4536 |
Warning(AfterMinusLoc, StringRef("duplicated register (") + |
| 4537 |
ARMInstPrinter::getRegisterName(Reg) + |
4537 |
ARMInstPrinter::getRegisterName(Reg) + |
| 4538 |
") in register list"); |
4538 |
") in register list"); |
| 4539 |
} |
4539 |
} |
| 4540 |
} |
4540 |
} |
| 4541 |
continue; |
4541 |
continue; |
| 4542 |
} |
4542 |
} |
| 4543 |
Parser.Lex(); // Eat the comma. |
4543 |
Parser.Lex(); // Eat the comma. |
| 4544 |
RegLoc = Parser.getTok().getLoc(); |
4544 |
RegLoc = Parser.getTok().getLoc(); |
| 4545 |
int OldReg = Reg; |
4545 |
int OldReg = Reg; |
| 4546 |
const AsmToken RegTok = Parser.getTok(); |
4546 |
const AsmToken RegTok = Parser.getTok(); |
| 4547 |
Reg = tryParseRegister(); |
4547 |
Reg = tryParseRegister(); |
| 4548 |
if (Reg == -1) |
4548 |
if (Reg == -1) |
| 4549 |
return Error(RegLoc, "register expected"); |
4549 |
return Error(RegLoc, "register expected"); |
| 4550 |
if (!AllowRAAC && Reg == ARM::RA_AUTH_CODE) |
4550 |
if (!AllowRAAC && Reg == ARM::RA_AUTH_CODE) |
| 4551 |
return Error(RegLoc, "pseudo-register not allowed"); |
4551 |
return Error(RegLoc, "pseudo-register not allowed"); |
| 4552 |
// Allow Q regs and just interpret them as the two D sub-registers. |
4552 |
// Allow Q regs and just interpret them as the two D sub-registers. |
| 4553 |
bool isQReg = false; |
4553 |
bool isQReg = false; |
| 4554 |
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { |
4554 |
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { |
| 4555 |
Reg = getDRegFromQReg(Reg); |
4555 |
Reg = getDRegFromQReg(Reg); |
| 4556 |
isQReg = true; |
4556 |
isQReg = true; |
| 4557 |
} |
4557 |
} |
| 4558 |
if (Reg != ARM::RA_AUTH_CODE && !RC->contains(Reg) && |
4558 |
if (Reg != ARM::RA_AUTH_CODE && !RC->contains(Reg) && |
| 4559 |
RC->getID() == ARMMCRegisterClasses[ARM::GPRRegClassID].getID() && |
4559 |
RC->getID() == ARMMCRegisterClasses[ARM::GPRRegClassID].getID() && |
| 4560 |
ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) { |
4560 |
ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) { |
| 4561 |
// switch the register classes, as GPRwithAPSRnospRegClassID is a partial |
4561 |
// switch the register classes, as GPRwithAPSRnospRegClassID is a partial |
| 4562 |
// subset of GPRRegClassId except it contains APSR as well. |
4562 |
// subset of GPRRegClassId except it contains APSR as well. |
| 4563 |
RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID]; |
4563 |
RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID]; |
| 4564 |
} |
4564 |
} |
| 4565 |
if (Reg == ARM::VPR && |
4565 |
if (Reg == ARM::VPR && |
| 4566 |
(RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] || |
4566 |
(RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] || |
| 4567 |
RC == &ARMMCRegisterClasses[ARM::DPRRegClassID] || |
4567 |
RC == &ARMMCRegisterClasses[ARM::DPRRegClassID] || |
| 4568 |
RC == &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID])) { |
4568 |
RC == &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID])) { |
| 4569 |
RC = &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID]; |
4569 |
RC = &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID]; |
| 4570 |
EReg = MRI->getEncodingValue(Reg); |
4570 |
EReg = MRI->getEncodingValue(Reg); |
| 4571 |
if (!insertNoDuplicates(Registers, EReg, Reg)) { |
4571 |
if (!insertNoDuplicates(Registers, EReg, Reg)) { |
| 4572 |
Warning(RegLoc, "duplicated register (" + RegTok.getString() + |
4572 |
Warning(RegLoc, "duplicated register (" + RegTok.getString() + |
| 4573 |
") in register list"); |
4573 |
") in register list"); |
| 4574 |
} |
4574 |
} |
| 4575 |
continue; |
4575 |
continue; |
| 4576 |
} |
4576 |
} |
| 4577 |
// The register must be in the same register class as the first. |
4577 |
// The register must be in the same register class as the first. |
| 4578 |
if ((Reg == ARM::RA_AUTH_CODE && |
4578 |
if ((Reg == ARM::RA_AUTH_CODE && |
| 4579 |
RC != &ARMMCRegisterClasses[ARM::GPRRegClassID]) || |
4579 |
RC != &ARMMCRegisterClasses[ARM::GPRRegClassID]) || |
| 4580 |
(Reg != ARM::RA_AUTH_CODE && !RC->contains(Reg))) |
4580 |
(Reg != ARM::RA_AUTH_CODE && !RC->contains(Reg))) |
| 4581 |
return Error(RegLoc, "invalid register in register list"); |
4581 |
return Error(RegLoc, "invalid register in register list"); |
| 4582 |
// In most cases, the list must be monotonically increasing. An |
4582 |
// In most cases, the list must be monotonically increasing. An |
| 4583 |
// exception is CLRM, which is order-independent anyway, so |
4583 |
// exception is CLRM, which is order-independent anyway, so |
| 4584 |
// there's no potential for confusion if you write clrm {r2,r1} |
4584 |
// there's no potential for confusion if you write clrm {r2,r1} |
| 4585 |
// instead of clrm {r1,r2}. |
4585 |
// instead of clrm {r1,r2}. |
| 4586 |
if (EnforceOrder && |
4586 |
if (EnforceOrder && |
| 4587 |
MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) { |
4587 |
MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) { |
| 4588 |
if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) |
4588 |
if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) |
| 4589 |
Warning(RegLoc, "register list not in ascending order"); |
4589 |
Warning(RegLoc, "register list not in ascending order"); |
| 4590 |
else if (!ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) |
4590 |
else if (!ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) |
| 4591 |
return Error(RegLoc, "register list not in ascending order"); |
4591 |
return Error(RegLoc, "register list not in ascending order"); |
| 4592 |
} |
4592 |
} |
| 4593 |
// VFP register lists must also be contiguous. |
4593 |
// VFP register lists must also be contiguous. |
| 4594 |
if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] && |
4594 |
if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] && |
| 4595 |
RC != &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID] && |
4595 |
RC != &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID] && |
| 4596 |
Reg != OldReg + 1) |
4596 |
Reg != OldReg + 1) |
| 4597 |
return Error(RegLoc, "non-contiguous register range"); |
4597 |
return Error(RegLoc, "non-contiguous register range"); |
| 4598 |
EReg = MRI->getEncodingValue(Reg); |
4598 |
EReg = MRI->getEncodingValue(Reg); |
| 4599 |
if (!insertNoDuplicates(Registers, EReg, Reg)) { |
4599 |
if (!insertNoDuplicates(Registers, EReg, Reg)) { |
| 4600 |
Warning(RegLoc, "duplicated register (" + RegTok.getString() + |
4600 |
Warning(RegLoc, "duplicated register (" + RegTok.getString() + |
| 4601 |
") in register list"); |
4601 |
") in register list"); |
| 4602 |
} |
4602 |
} |
| 4603 |
if (isQReg) { |
4603 |
if (isQReg) { |
| 4604 |
EReg = MRI->getEncodingValue(++Reg); |
4604 |
EReg = MRI->getEncodingValue(++Reg); |
| 4605 |
Registers.emplace_back(EReg, Reg); |
4605 |
Registers.emplace_back(EReg, Reg); |
| 4606 |
} |
4606 |
} |
| 4607 |
} |
4607 |
} |
| 4608 |
|
4608 |
|
| 4609 |
if (Parser.getTok().isNot(AsmToken::RCurly)) |
4609 |
if (Parser.getTok().isNot(AsmToken::RCurly)) |
| 4610 |
return Error(Parser.getTok().getLoc(), "'}' expected"); |
4610 |
return Error(Parser.getTok().getLoc(), "'}' expected"); |
| 4611 |
SMLoc E = Parser.getTok().getEndLoc(); |
4611 |
SMLoc E = Parser.getTok().getEndLoc(); |
| 4612 |
Parser.Lex(); // Eat '}' token. |
4612 |
Parser.Lex(); // Eat '}' token. |
| 4613 |
|
4613 |
|
| 4614 |
// Push the register list operand. |
4614 |
// Push the register list operand. |
| 4615 |
Operands.push_back(ARMOperand::CreateRegList(Registers, S, E)); |
4615 |
Operands.push_back(ARMOperand::CreateRegList(Registers, S, E)); |
| 4616 |
|
4616 |
|
| 4617 |
// The ARM system instruction variants for LDM/STM have a '^' token here. |
4617 |
// The ARM system instruction variants for LDM/STM have a '^' token here. |
| 4618 |
if (Parser.getTok().is(AsmToken::Caret)) { |
4618 |
if (Parser.getTok().is(AsmToken::Caret)) { |
| 4619 |
Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc())); |
4619 |
Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc())); |
| 4620 |
Parser.Lex(); // Eat '^' token. |
4620 |
Parser.Lex(); // Eat '^' token. |
| 4621 |
} |
4621 |
} |
| 4622 |
|
4622 |
|
| 4623 |
return false; |
4623 |
return false; |
| 4624 |
} |
4624 |
} |
| 4625 |
|
4625 |
|
| 4626 |
// Helper function to parse the lane index for vector lists. |
4626 |
// Helper function to parse the lane index for vector lists. |
| 4627 |
ParseStatus ARMAsmParser::parseVectorLane(VectorLaneTy &LaneKind, |
4627 |
ParseStatus ARMAsmParser::parseVectorLane(VectorLaneTy &LaneKind, |
| 4628 |
unsigned &Index, SMLoc &EndLoc) { |
4628 |
unsigned &Index, SMLoc &EndLoc) { |
| 4629 |
MCAsmParser &Parser = getParser(); |
4629 |
MCAsmParser &Parser = getParser(); |
| 4630 |
Index = 0; // Always return a defined index value. |
4630 |
Index = 0; // Always return a defined index value. |
| 4631 |
if (Parser.getTok().is(AsmToken::LBrac)) { |
4631 |
if (Parser.getTok().is(AsmToken::LBrac)) { |
| 4632 |
Parser.Lex(); // Eat the '['. |
4632 |
Parser.Lex(); // Eat the '['. |
| 4633 |
if (Parser.getTok().is(AsmToken::RBrac)) { |
4633 |
if (Parser.getTok().is(AsmToken::RBrac)) { |
| 4634 |
// "Dn[]" is the 'all lanes' syntax. |
4634 |
// "Dn[]" is the 'all lanes' syntax. |
| 4635 |
LaneKind = AllLanes; |
4635 |
LaneKind = AllLanes; |
| 4636 |
EndLoc = Parser.getTok().getEndLoc(); |
4636 |
EndLoc = Parser.getTok().getEndLoc(); |
| 4637 |
Parser.Lex(); // Eat the ']'. |
4637 |
Parser.Lex(); // Eat the ']'. |
| 4638 |
return ParseStatus::Success; |
4638 |
return ParseStatus::Success; |
| 4639 |
} |
4639 |
} |
| 4640 |
|
4640 |
|
| 4641 |
// There's an optional '#' token here. Normally there wouldn't be, but |
4641 |
// There's an optional '#' token here. Normally there wouldn't be, but |
| 4642 |
// inline assemble puts one in, and it's friendly to accept that. |
4642 |
// inline assemble puts one in, and it's friendly to accept that. |
| 4643 |
if (Parser.getTok().is(AsmToken::Hash)) |
4643 |
if (Parser.getTok().is(AsmToken::Hash)) |
| 4644 |
Parser.Lex(); // Eat '#' or '$'. |
4644 |
Parser.Lex(); // Eat '#' or '$'. |
| 4645 |
|
4645 |
|
| 4646 |
const MCExpr *LaneIndex; |
4646 |
const MCExpr *LaneIndex; |
| 4647 |
SMLoc Loc = Parser.getTok().getLoc(); |
4647 |
SMLoc Loc = Parser.getTok().getLoc(); |
| 4648 |
if (getParser().parseExpression(LaneIndex)) |
4648 |
if (getParser().parseExpression(LaneIndex)) |
| 4649 |
return Error(Loc, "illegal expression"); |
4649 |
return Error(Loc, "illegal expression"); |
| 4650 |
const MCConstantExpr *CE = dyn_cast(LaneIndex); |
4650 |
const MCConstantExpr *CE = dyn_cast(LaneIndex); |
| 4651 |
if (!CE) |
4651 |
if (!CE) |
| 4652 |
return Error(Loc, "lane index must be empty or an integer"); |
4652 |
return Error(Loc, "lane index must be empty or an integer"); |
| 4653 |
if (Parser.getTok().isNot(AsmToken::RBrac)) |
4653 |
if (Parser.getTok().isNot(AsmToken::RBrac)) |
| 4654 |
return Error(Parser.getTok().getLoc(), "']' expected"); |
4654 |
return Error(Parser.getTok().getLoc(), "']' expected"); |
| 4655 |
EndLoc = Parser.getTok().getEndLoc(); |
4655 |
EndLoc = Parser.getTok().getEndLoc(); |
| 4656 |
Parser.Lex(); // Eat the ']'. |
4656 |
Parser.Lex(); // Eat the ']'. |
| 4657 |
int64_t Val = CE->getValue(); |
4657 |
int64_t Val = CE->getValue(); |
| 4658 |
|
4658 |
|
| 4659 |
// FIXME: Make this range check context sensitive for .8, .16, .32. |
4659 |
// FIXME: Make this range check context sensitive for .8, .16, .32. |
| 4660 |
if (Val < 0 || Val > 7) |
4660 |
if (Val < 0 || Val > 7) |
| 4661 |
return Error(Parser.getTok().getLoc(), "lane index out of range"); |
4661 |
return Error(Parser.getTok().getLoc(), "lane index out of range"); |
| 4662 |
Index = Val; |
4662 |
Index = Val; |
| 4663 |
LaneKind = IndexedLane; |
4663 |
LaneKind = IndexedLane; |
| 4664 |
return ParseStatus::Success; |
4664 |
return ParseStatus::Success; |
| 4665 |
} |
4665 |
} |
| 4666 |
LaneKind = NoLanes; |
4666 |
LaneKind = NoLanes; |
| 4667 |
return ParseStatus::Success; |
4667 |
return ParseStatus::Success; |
| 4668 |
} |
4668 |
} |
| 4669 |
|
4669 |
|
| 4670 |
// parse a vector register list |
4670 |
// parse a vector register list |
| 4671 |
ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { |
4671 |
ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { |
| 4672 |
MCAsmParser &Parser = getParser(); |
4672 |
MCAsmParser &Parser = getParser(); |
| 4673 |
VectorLaneTy LaneKind; |
4673 |
VectorLaneTy LaneKind; |
| 4674 |
unsigned LaneIndex; |
4674 |
unsigned LaneIndex; |
| 4675 |
SMLoc S = Parser.getTok().getLoc(); |
4675 |
SMLoc S = Parser.getTok().getLoc(); |
| 4676 |
// As an extension (to match gas), support a plain D register or Q register |
4676 |
// As an extension (to match gas), support a plain D register or Q register |
| 4677 |
// (without encosing curly braces) as a single or double entry list, |
4677 |
// (without encosing curly braces) as a single or double entry list, |
| 4678 |
// respectively. |
4678 |
// respectively. |
| 4679 |
if (!hasMVE() && Parser.getTok().is(AsmToken::Identifier)) { |
4679 |
if (!hasMVE() && Parser.getTok().is(AsmToken::Identifier)) { |
| 4680 |
SMLoc E = Parser.getTok().getEndLoc(); |
4680 |
SMLoc E = Parser.getTok().getEndLoc(); |
| 4681 |
int Reg = tryParseRegister(); |
4681 |
int Reg = tryParseRegister(); |
| 4682 |
if (Reg == -1) |
4682 |
if (Reg == -1) |
| 4683 |
return ParseStatus::NoMatch; |
4683 |
return ParseStatus::NoMatch; |
| 4684 |
if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) { |
4684 |
if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) { |
| 4685 |
ParseStatus Res = parseVectorLane(LaneKind, LaneIndex, E); |
4685 |
ParseStatus Res = parseVectorLane(LaneKind, LaneIndex, E); |
| 4686 |
if (!Res.isSuccess()) |
4686 |
if (!Res.isSuccess()) |
| 4687 |
return Res; |
4687 |
return Res; |
| 4688 |
switch (LaneKind) { |
4688 |
switch (LaneKind) { |
| 4689 |
case NoLanes: |
4689 |
case NoLanes: |
| 4690 |
Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E)); |
4690 |
Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E)); |
| 4691 |
break; |
4691 |
break; |
| 4692 |
case AllLanes: |
4692 |
case AllLanes: |
| 4693 |
Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false, |
4693 |
Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false, |
| 4694 |
S, E)); |
4694 |
S, E)); |
| 4695 |
break; |
4695 |
break; |
| 4696 |
case IndexedLane: |
4696 |
case IndexedLane: |
| 4697 |
Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1, |
4697 |
Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1, |
| 4698 |
LaneIndex, |
4698 |
LaneIndex, |
| 4699 |
false, S, E)); |
4699 |
false, S, E)); |
| 4700 |
break; |
4700 |
break; |
| 4701 |
} |
4701 |
} |
| 4702 |
return ParseStatus::Success; |
4702 |
return ParseStatus::Success; |
| 4703 |
} |
4703 |
} |
| 4704 |
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { |
4704 |
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { |
| 4705 |
Reg = getDRegFromQReg(Reg); |
4705 |
Reg = getDRegFromQReg(Reg); |
| 4706 |
ParseStatus Res = parseVectorLane(LaneKind, LaneIndex, E); |
4706 |
ParseStatus Res = parseVectorLane(LaneKind, LaneIndex, E); |
| 4707 |
if (!Res.isSuccess()) |
4707 |
if (!Res.isSuccess()) |
| 4708 |
return Res; |
4708 |
return Res; |
| 4709 |
switch (LaneKind) { |
4709 |
switch (LaneKind) { |
| 4710 |
case NoLanes: |
4710 |
case NoLanes: |
| 4711 |
Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, |
4711 |
Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, |
| 4712 |
&ARMMCRegisterClasses[ARM::DPairRegClassID]); |
4712 |
&ARMMCRegisterClasses[ARM::DPairRegClassID]); |
| 4713 |
Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E)); |
4713 |
Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E)); |
| 4714 |
break; |
4714 |
break; |
| 4715 |
case AllLanes: |
4715 |
case AllLanes: |
| 4716 |
Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, |
4716 |
Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, |
| 4717 |
&ARMMCRegisterClasses[ARM::DPairRegClassID]); |
4717 |
&ARMMCRegisterClasses[ARM::DPairRegClassID]); |
| 4718 |
Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false, |
4718 |
Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false, |
| 4719 |
S, E)); |
4719 |
S, E)); |
| 4720 |
break; |
4720 |
break; |
| 4721 |
case IndexedLane: |
4721 |
case IndexedLane: |
| 4722 |
Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2, |
4722 |
Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2, |
| 4723 |
LaneIndex, |
4723 |
LaneIndex, |
| 4724 |
false, S, E)); |
4724 |
false, S, E)); |
| 4725 |
break; |
4725 |
break; |
| 4726 |
} |
4726 |
} |
| 4727 |
return ParseStatus::Success; |
4727 |
return ParseStatus::Success; |
| 4728 |
} |
4728 |
} |
| 4729 |
return Error(S, "vector register expected"); |
4729 |
return Error(S, "vector register expected"); |
| 4730 |
} |
4730 |
} |
| 4731 |
|
4731 |
|
| 4732 |
if (Parser.getTok().isNot(AsmToken::LCurly)) |
4732 |
if (Parser.getTok().isNot(AsmToken::LCurly)) |
| 4733 |
return ParseStatus::NoMatch; |
4733 |
return ParseStatus::NoMatch; |
| 4734 |
|
4734 |
|
| 4735 |
Parser.Lex(); // Eat '{' token. |
4735 |
Parser.Lex(); // Eat '{' token. |
| 4736 |
SMLoc RegLoc = Parser.getTok().getLoc(); |
4736 |
SMLoc RegLoc = Parser.getTok().getLoc(); |
| 4737 |
|
4737 |
|
| 4738 |
int Reg = tryParseRegister(); |
4738 |
int Reg = tryParseRegister(); |
| 4739 |
if (Reg == -1) |
4739 |
if (Reg == -1) |
| 4740 |
return Error(RegLoc, "register expected"); |
4740 |
return Error(RegLoc, "register expected"); |
| 4741 |
unsigned Count = 1; |
4741 |
unsigned Count = 1; |
| 4742 |
int Spacing = 0; |
4742 |
int Spacing = 0; |
| 4743 |
unsigned FirstReg = Reg; |
4743 |
unsigned FirstReg = Reg; |
| 4744 |
|
4744 |
|
| 4745 |
if (hasMVE() && !ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(Reg)) |
4745 |
if (hasMVE() && !ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(Reg)) |
| 4746 |
return Error(Parser.getTok().getLoc(), |
4746 |
return Error(Parser.getTok().getLoc(), |
| 4747 |
"vector register in range Q0-Q7 expected"); |
4747 |
"vector register in range Q0-Q7 expected"); |
| 4748 |
// The list is of D registers, but we also allow Q regs and just interpret |
4748 |
// The list is of D registers, but we also allow Q regs and just interpret |
| 4749 |
// them as the two D sub-registers. |
4749 |
// them as the two D sub-registers. |
| 4750 |
else if (!hasMVE() && ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { |
4750 |
else if (!hasMVE() && ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { |
| 4751 |
FirstReg = Reg = getDRegFromQReg(Reg); |
4751 |
FirstReg = Reg = getDRegFromQReg(Reg); |
| 4752 |
Spacing = 1; // double-spacing requires explicit D registers, otherwise |
4752 |
Spacing = 1; // double-spacing requires explicit D registers, otherwise |
| 4753 |
// it's ambiguous with four-register single spaced. |
4753 |
// it's ambiguous with four-register single spaced. |
| 4754 |
++Reg; |
4754 |
++Reg; |
| 4755 |
++Count; |
4755 |
++Count; |
| 4756 |
} |
4756 |
} |
| 4757 |
|
4757 |
|
| 4758 |
SMLoc E; |
4758 |
SMLoc E; |
| 4759 |
if (!parseVectorLane(LaneKind, LaneIndex, E).isSuccess()) |
4759 |
if (!parseVectorLane(LaneKind, LaneIndex, E).isSuccess()) |
| 4760 |
return ParseStatus::Failure; |
4760 |
return ParseStatus::Failure; |
| 4761 |
|
4761 |
|
| 4762 |
while (Parser.getTok().is(AsmToken::Comma) || |
4762 |
while (Parser.getTok().is(AsmToken::Comma) || |
| 4763 |
Parser.getTok().is(AsmToken::Minus)) { |
4763 |
Parser.getTok().is(AsmToken::Minus)) { |
| 4764 |
if (Parser.getTok().is(AsmToken::Minus)) { |
4764 |
if (Parser.getTok().is(AsmToken::Minus)) { |
| 4765 |
if (!Spacing) |
4765 |
if (!Spacing) |
| 4766 |
Spacing = 1; // Register range implies a single spaced list. |
4766 |
Spacing = 1; // Register range implies a single spaced list. |
| 4767 |
else if (Spacing == 2) |
4767 |
else if (Spacing == 2) |
| 4768 |
return Error(Parser.getTok().getLoc(), |
4768 |
return Error(Parser.getTok().getLoc(), |
| 4769 |
"sequential registers in double spaced list"); |
4769 |
"sequential registers in double spaced list"); |
| 4770 |
Parser.Lex(); // Eat the minus. |
4770 |
Parser.Lex(); // Eat the minus. |
| 4771 |
SMLoc AfterMinusLoc = Parser.getTok().getLoc(); |
4771 |
SMLoc AfterMinusLoc = Parser.getTok().getLoc(); |
| 4772 |
int EndReg = tryParseRegister(); |
4772 |
int EndReg = tryParseRegister(); |
| 4773 |
if (EndReg == -1) |
4773 |
if (EndReg == -1) |
| 4774 |
return Error(AfterMinusLoc, "register expected"); |
4774 |
return Error(AfterMinusLoc, "register expected"); |
| 4775 |
// Allow Q regs and just interpret them as the two D sub-registers. |
4775 |
// Allow Q regs and just interpret them as the two D sub-registers. |
| 4776 |
if (!hasMVE() && ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg)) |
4776 |
if (!hasMVE() && ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg)) |
| 4777 |
EndReg = getDRegFromQReg(EndReg) + 1; |
4777 |
EndReg = getDRegFromQReg(EndReg) + 1; |
| 4778 |
// If the register is the same as the start reg, there's nothing |
4778 |
// If the register is the same as the start reg, there's nothing |
| 4779 |
// more to do. |
4779 |
// more to do. |
| 4780 |
if (Reg == EndReg) |
4780 |
if (Reg == EndReg) |
| 4781 |
continue; |
4781 |
continue; |
| 4782 |
// The register must be in the same register class as the first. |
4782 |
// The register must be in the same register class as the first. |
| 4783 |
if ((hasMVE() && |
4783 |
if ((hasMVE() && |
| 4784 |
!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(EndReg)) || |
4784 |
!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(EndReg)) || |
| 4785 |
(!hasMVE() && |
4785 |
(!hasMVE() && |
| 4786 |
!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg))) |
4786 |
!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg))) |
| 4787 |
return Error(AfterMinusLoc, "invalid register in register list"); |
4787 |
return Error(AfterMinusLoc, "invalid register in register list"); |
| 4788 |
// Ranges must go from low to high. |
4788 |
// Ranges must go from low to high. |
| 4789 |
if (Reg > EndReg) |
4789 |
if (Reg > EndReg) |
| 4790 |
return Error(AfterMinusLoc, "bad range in register list"); |
4790 |
return Error(AfterMinusLoc, "bad range in register list"); |
| 4791 |
// Parse the lane specifier if present. |
4791 |
// Parse the lane specifier if present. |
| 4792 |
VectorLaneTy NextLaneKind; |
4792 |
VectorLaneTy NextLaneKind; |
| 4793 |
unsigned NextLaneIndex; |
4793 |
unsigned NextLaneIndex; |
| 4794 |
if (!parseVectorLane(NextLaneKind, NextLaneIndex, E).isSuccess()) |
4794 |
if (!parseVectorLane(NextLaneKind, NextLaneIndex, E).isSuccess()) |
| 4795 |
return ParseStatus::Failure; |
4795 |
return ParseStatus::Failure; |
| 4796 |
if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) |
4796 |
if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) |
| 4797 |
return Error(AfterMinusLoc, "mismatched lane index in register list"); |
4797 |
return Error(AfterMinusLoc, "mismatched lane index in register list"); |
| 4798 |
|
4798 |
|
| 4799 |
// Add all the registers in the range to the register list. |
4799 |
// Add all the registers in the range to the register list. |
| 4800 |
Count += EndReg - Reg; |
4800 |
Count += EndReg - Reg; |
| 4801 |
Reg = EndReg; |
4801 |
Reg = EndReg; |
| 4802 |
continue; |
4802 |
continue; |
| 4803 |
} |
4803 |
} |
| 4804 |
Parser.Lex(); // Eat the comma. |
4804 |
Parser.Lex(); // Eat the comma. |
| 4805 |
RegLoc = Parser.getTok().getLoc(); |
4805 |
RegLoc = Parser.getTok().getLoc(); |
| 4806 |
int OldReg = Reg; |
4806 |
int OldReg = Reg; |
| 4807 |
Reg = tryParseRegister(); |
4807 |
Reg = tryParseRegister(); |
| 4808 |
if (Reg == -1) |
4808 |
if (Reg == -1) |
| 4809 |
return Error(RegLoc, "register expected"); |
4809 |
return Error(RegLoc, "register expected"); |
| 4810 |
|
4810 |
|
| 4811 |
if (hasMVE()) { |
4811 |
if (hasMVE()) { |
| 4812 |
if (!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(Reg)) |
4812 |
if (!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(Reg)) |
| 4813 |
return Error(RegLoc, "vector register in range Q0-Q7 expected"); |
4813 |
return Error(RegLoc, "vector register in range Q0-Q7 expected"); |
| 4814 |
Spacing = 1; |
4814 |
Spacing = 1; |
| 4815 |
} |
4815 |
} |
| 4816 |
// vector register lists must be contiguous. |
4816 |
// vector register lists must be contiguous. |
| 4817 |
// It's OK to use the enumeration values directly here rather, as the |
4817 |
// It's OK to use the enumeration values directly here rather, as the |
| 4818 |
// VFP register classes have the enum sorted properly. |
4818 |
// VFP register classes have the enum sorted properly. |
| 4819 |
// |
4819 |
// |
| 4820 |
// The list is of D registers, but we also allow Q regs and just interpret |
4820 |
// The list is of D registers, but we also allow Q regs and just interpret |
| 4821 |
// them as the two D sub-registers. |
4821 |
// them as the two D sub-registers. |
| 4822 |
else if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { |
4822 |
else if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { |
| 4823 |
if (!Spacing) |
4823 |
if (!Spacing) |
| 4824 |
Spacing = 1; // Register range implies a single spaced list. |
4824 |
Spacing = 1; // Register range implies a single spaced list. |
| 4825 |
else if (Spacing == 2) |
4825 |
else if (Spacing == 2) |
| 4826 |
return Error( |
4826 |
return Error( |
| 4827 |
RegLoc, |
4827 |
RegLoc, |
| 4828 |
"invalid register in double-spaced list (must be 'D' register')"); |
4828 |
"invalid register in double-spaced list (must be 'D' register')"); |
| 4829 |
Reg = getDRegFromQReg(Reg); |
4829 |
Reg = getDRegFromQReg(Reg); |
| 4830 |
if (Reg != OldReg + 1) |
4830 |
if (Reg != OldReg + 1) |
| 4831 |
return Error(RegLoc, "non-contiguous register range"); |
4831 |
return Error(RegLoc, "non-contiguous register range"); |
| 4832 |
++Reg; |
4832 |
++Reg; |
| 4833 |
Count += 2; |
4833 |
Count += 2; |
| 4834 |
// Parse the lane specifier if present. |
4834 |
// Parse the lane specifier if present. |
| 4835 |
VectorLaneTy NextLaneKind; |
4835 |
VectorLaneTy NextLaneKind; |
| 4836 |
unsigned NextLaneIndex; |
4836 |
unsigned NextLaneIndex; |
| 4837 |
SMLoc LaneLoc = Parser.getTok().getLoc(); |
4837 |
SMLoc LaneLoc = Parser.getTok().getLoc(); |
| 4838 |
if (!parseVectorLane(NextLaneKind, NextLaneIndex, E).isSuccess()) |
4838 |
if (!parseVectorLane(NextLaneKind, NextLaneIndex, E).isSuccess()) |
| 4839 |
return ParseStatus::Failure; |
4839 |
return ParseStatus::Failure; |
| 4840 |
if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) |
4840 |
if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) |
| 4841 |
return Error(LaneLoc, "mismatched lane index in register list"); |
4841 |
return Error(LaneLoc, "mismatched lane index in register list"); |
| 4842 |
continue; |
4842 |
continue; |
| 4843 |
} |
4843 |
} |
| 4844 |
// Normal D register. |
4844 |
// Normal D register. |
| 4845 |
// Figure out the register spacing (single or double) of the list if |
4845 |
// Figure out the register spacing (single or double) of the list if |
| 4846 |
// we don't know it already. |
4846 |
// we don't know it already. |
| 4847 |
if (!Spacing) |
4847 |
if (!Spacing) |
| 4848 |
Spacing = 1 + (Reg == OldReg + 2); |
4848 |
Spacing = 1 + (Reg == OldReg + 2); |
| 4849 |
|
4849 |
|
| 4850 |
// Just check that it's contiguous and keep going. |
4850 |
// Just check that it's contiguous and keep going. |
| 4851 |
if (Reg != OldReg + Spacing) |
4851 |
if (Reg != OldReg + Spacing) |
| 4852 |
return Error(RegLoc, "non-contiguous register range"); |
4852 |
return Error(RegLoc, "non-contiguous register range"); |
| 4853 |
++Count; |
4853 |
++Count; |
| 4854 |
// Parse the lane specifier if present. |
4854 |
// Parse the lane specifier if present. |
| 4855 |
VectorLaneTy NextLaneKind; |
4855 |
VectorLaneTy NextLaneKind; |
| 4856 |
unsigned NextLaneIndex; |
4856 |
unsigned NextLaneIndex; |
| 4857 |
SMLoc EndLoc = Parser.getTok().getLoc(); |
4857 |
SMLoc EndLoc = Parser.getTok().getLoc(); |
| 4858 |
if (!parseVectorLane(NextLaneKind, NextLaneIndex, E).isSuccess()) |
4858 |
if (!parseVectorLane(NextLaneKind, NextLaneIndex, E).isSuccess()) |
| 4859 |
return ParseStatus::Failure; |
4859 |
return ParseStatus::Failure; |
| 4860 |
if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) |
4860 |
if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) |
| 4861 |
return Error(EndLoc, "mismatched lane index in register list"); |
4861 |
return Error(EndLoc, "mismatched lane index in register list"); |
| 4862 |
} |
4862 |
} |
| 4863 |
|
4863 |
|
| 4864 |
if (Parser.getTok().isNot(AsmToken::RCurly)) |
4864 |
if (Parser.getTok().isNot(AsmToken::RCurly)) |
| 4865 |
return Error(Parser.getTok().getLoc(), "'}' expected"); |
4865 |
return Error(Parser.getTok().getLoc(), "'}' expected"); |
| 4866 |
E = Parser.getTok().getEndLoc(); |
4866 |
E = Parser.getTok().getEndLoc(); |
| 4867 |
Parser.Lex(); // Eat '}' token. |
4867 |
Parser.Lex(); // Eat '}' token. |
| 4868 |
|
4868 |
|
| 4869 |
switch (LaneKind) { |
4869 |
switch (LaneKind) { |
| 4870 |
case NoLanes: |
4870 |
case NoLanes: |
| 4871 |
case AllLanes: { |
4871 |
case AllLanes: { |
| 4872 |
// Two-register operands have been converted to the |
4872 |
// Two-register operands have been converted to the |
| 4873 |
// composite register classes. |
4873 |
// composite register classes. |
| 4874 |
if (Count == 2 && !hasMVE()) { |
4874 |
if (Count == 2 && !hasMVE()) { |
| 4875 |
const MCRegisterClass *RC = (Spacing == 1) ? |
4875 |
const MCRegisterClass *RC = (Spacing == 1) ? |
| 4876 |
&ARMMCRegisterClasses[ARM::DPairRegClassID] : |
4876 |
&ARMMCRegisterClasses[ARM::DPairRegClassID] : |
| 4877 |
&ARMMCRegisterClasses[ARM::DPairSpcRegClassID]; |
4877 |
&ARMMCRegisterClasses[ARM::DPairSpcRegClassID]; |
| 4878 |
FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC); |
4878 |
FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC); |
| 4879 |
} |
4879 |
} |
| 4880 |
auto Create = (LaneKind == NoLanes ? ARMOperand::CreateVectorList : |
4880 |
auto Create = (LaneKind == NoLanes ? ARMOperand::CreateVectorList : |
| 4881 |
ARMOperand::CreateVectorListAllLanes); |
4881 |
ARMOperand::CreateVectorListAllLanes); |
| 4882 |
Operands.push_back(Create(FirstReg, Count, (Spacing == 2), S, E)); |
4882 |
Operands.push_back(Create(FirstReg, Count, (Spacing == 2), S, E)); |
| 4883 |
break; |
4883 |
break; |
| 4884 |
} |
4884 |
} |
| 4885 |
case IndexedLane: |
4885 |
case IndexedLane: |
| 4886 |
Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count, |
4886 |
Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count, |
| 4887 |
LaneIndex, |
4887 |
LaneIndex, |
| 4888 |
(Spacing == 2), |
4888 |
(Spacing == 2), |
| 4889 |
S, E)); |
4889 |
S, E)); |
| 4890 |
break; |
4890 |
break; |
| 4891 |
} |
4891 |
} |
| 4892 |
return ParseStatus::Success; |
4892 |
return ParseStatus::Success; |
| 4893 |
} |
4893 |
} |
| 4894 |
|
4894 |
|
| 4895 |
/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options. |
4895 |
/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options. |
| 4896 |
ParseStatus ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) { |
4896 |
ParseStatus ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) { |
| 4897 |
MCAsmParser &Parser = getParser(); |
4897 |
MCAsmParser &Parser = getParser(); |
| 4898 |
SMLoc S = Parser.getTok().getLoc(); |
4898 |
SMLoc S = Parser.getTok().getLoc(); |
| 4899 |
const AsmToken &Tok = Parser.getTok(); |
4899 |
const AsmToken &Tok = Parser.getTok(); |
| 4900 |
unsigned Opt; |
4900 |
unsigned Opt; |
| 4901 |
|
4901 |
|
| 4902 |
if (Tok.is(AsmToken::Identifier)) { |
4902 |
if (Tok.is(AsmToken::Identifier)) { |
| 4903 |
StringRef OptStr = Tok.getString(); |
4903 |
StringRef OptStr = Tok.getString(); |
| 4904 |
|
4904 |
|
| 4905 |
Opt = StringSwitch(OptStr.slice(0, OptStr.size()).lower()) |
4905 |
Opt = StringSwitch(OptStr.slice(0, OptStr.size()).lower()) |
| 4906 |
.Case("sy", ARM_MB::SY) |
4906 |
.Case("sy", ARM_MB::SY) |
| 4907 |
.Case("st", ARM_MB::ST) |
4907 |
.Case("st", ARM_MB::ST) |
| 4908 |
.Case("ld", ARM_MB::LD) |
4908 |
.Case("ld", ARM_MB::LD) |
| 4909 |
.Case("sh", ARM_MB::ISH) |
4909 |
.Case("sh", ARM_MB::ISH) |
| 4910 |
.Case("ish", ARM_MB::ISH) |
4910 |
.Case("ish", ARM_MB::ISH) |
| 4911 |
.Case("shst", ARM_MB::ISHST) |
4911 |
.Case("shst", ARM_MB::ISHST) |
| 4912 |
.Case("ishst", ARM_MB::ISHST) |
4912 |
.Case("ishst", ARM_MB::ISHST) |
| 4913 |
.Case("ishld", ARM_MB::ISHLD) |
4913 |
.Case("ishld", ARM_MB::ISHLD) |
| 4914 |
.Case("nsh", ARM_MB::NSH) |
4914 |
.Case("nsh", ARM_MB::NSH) |
| 4915 |
.Case("un", ARM_MB::NSH) |
4915 |
.Case("un", ARM_MB::NSH) |
| 4916 |
.Case("nshst", ARM_MB::NSHST) |
4916 |
.Case("nshst", ARM_MB::NSHST) |
| 4917 |
.Case("nshld", ARM_MB::NSHLD) |
4917 |
.Case("nshld", ARM_MB::NSHLD) |
| 4918 |
.Case("unst", ARM_MB::NSHST) |
4918 |
.Case("unst", ARM_MB::NSHST) |
| 4919 |
.Case("osh", ARM_MB::OSH) |
4919 |
.Case("osh", ARM_MB::OSH) |
| 4920 |
.Case("oshst", ARM_MB::OSHST) |
4920 |
.Case("oshst", ARM_MB::OSHST) |
| 4921 |
.Case("oshld", ARM_MB::OSHLD) |
4921 |
.Case("oshld", ARM_MB::OSHLD) |
| 4922 |
.Default(~0U); |
4922 |
.Default(~0U); |
| 4923 |
|
4923 |
|
| 4924 |
// ishld, oshld, nshld and ld are only available from ARMv8. |
4924 |
// ishld, oshld, nshld and ld are only available from ARMv8. |
| 4925 |
if (!hasV8Ops() && (Opt == ARM_MB::ISHLD || Opt == ARM_MB::OSHLD || |
4925 |
if (!hasV8Ops() && (Opt == ARM_MB::ISHLD || Opt == ARM_MB::OSHLD || |
| 4926 |
Opt == ARM_MB::NSHLD || Opt == ARM_MB::LD)) |
4926 |
Opt == ARM_MB::NSHLD || Opt == ARM_MB::LD)) |
| 4927 |
Opt = ~0U; |
4927 |
Opt = ~0U; |
| 4928 |
|
4928 |
|
| 4929 |
if (Opt == ~0U) |
4929 |
if (Opt == ~0U) |
| 4930 |
return ParseStatus::NoMatch; |
4930 |
return ParseStatus::NoMatch; |
| 4931 |
|
4931 |
|
| 4932 |
Parser.Lex(); // Eat identifier token. |
4932 |
Parser.Lex(); // Eat identifier token. |
| 4933 |
} else if (Tok.is(AsmToken::Hash) || |
4933 |
} else if (Tok.is(AsmToken::Hash) || |
| 4934 |
Tok.is(AsmToken::Dollar) || |
4934 |
Tok.is(AsmToken::Dollar) || |
| 4935 |
Tok.is(AsmToken::Integer)) { |
4935 |
Tok.is(AsmToken::Integer)) { |
| 4936 |
if (Parser.getTok().isNot(AsmToken::Integer)) |
4936 |
if (Parser.getTok().isNot(AsmToken::Integer)) |
| 4937 |
Parser.Lex(); // Eat '#' or '$'. |
4937 |
Parser.Lex(); // Eat '#' or '$'. |
| 4938 |
SMLoc Loc = Parser.getTok().getLoc(); |
4938 |
SMLoc Loc = Parser.getTok().getLoc(); |
| 4939 |
|
4939 |
|
| 4940 |
const MCExpr *MemBarrierID; |
4940 |
const MCExpr *MemBarrierID; |
| 4941 |
if (getParser().parseExpression(MemBarrierID)) |
4941 |
if (getParser().parseExpression(MemBarrierID)) |
| 4942 |
return Error(Loc, "illegal expression"); |
4942 |
return Error(Loc, "illegal expression"); |
| 4943 |
|
4943 |
|
| 4944 |
const MCConstantExpr *CE = dyn_cast(MemBarrierID); |
4944 |
const MCConstantExpr *CE = dyn_cast(MemBarrierID); |
| 4945 |
if (!CE) |
4945 |
if (!CE) |
| 4946 |
return Error(Loc, "constant expression expected"); |
4946 |
return Error(Loc, "constant expression expected"); |
| 4947 |
|
4947 |
|
| 4948 |
int Val = CE->getValue(); |
4948 |
int Val = CE->getValue(); |
| 4949 |
if (Val & ~0xf) |
4949 |
if (Val & ~0xf) |
| 4950 |
return Error(Loc, "immediate value out of range"); |
4950 |
return Error(Loc, "immediate value out of range"); |
| 4951 |
|
4951 |
|
| 4952 |
Opt = ARM_MB::RESERVED_0 + Val; |
4952 |
Opt = ARM_MB::RESERVED_0 + Val; |
| 4953 |
} else |
4953 |
} else |
| 4954 |
return ParseStatus::Failure; |
4954 |
return ParseStatus::Failure; |
| 4955 |
|
4955 |
|
| 4956 |
Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S)); |
4956 |
Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S)); |
| 4957 |
return ParseStatus::Success; |
4957 |
return ParseStatus::Success; |
| 4958 |
} |
4958 |
} |
| 4959 |
|
4959 |
|
| 4960 |
ParseStatus |
4960 |
ParseStatus |
| 4961 |
ARMAsmParser::parseTraceSyncBarrierOptOperand(OperandVector &Operands) { |
4961 |
ARMAsmParser::parseTraceSyncBarrierOptOperand(OperandVector &Operands) { |
| 4962 |
MCAsmParser &Parser = getParser(); |
4962 |
MCAsmParser &Parser = getParser(); |
| 4963 |
SMLoc S = Parser.getTok().getLoc(); |
4963 |
SMLoc S = Parser.getTok().getLoc(); |
| 4964 |
const AsmToken &Tok = Parser.getTok(); |
4964 |
const AsmToken &Tok = Parser.getTok(); |
| 4965 |
|
4965 |
|
| 4966 |
if (Tok.isNot(AsmToken::Identifier)) |
4966 |
if (Tok.isNot(AsmToken::Identifier)) |
| 4967 |
return ParseStatus::NoMatch; |
4967 |
return ParseStatus::NoMatch; |
| 4968 |
|
4968 |
|
| 4969 |
if (!Tok.getString().equals_insensitive("csync")) |
4969 |
if (!Tok.getString().equals_insensitive("csync")) |
| 4970 |
return ParseStatus::NoMatch; |
4970 |
return ParseStatus::NoMatch; |
| 4971 |
|
4971 |
|
| 4972 |
Parser.Lex(); // Eat identifier token. |
4972 |
Parser.Lex(); // Eat identifier token. |
| 4973 |
|
4973 |
|
| 4974 |
Operands.push_back(ARMOperand::CreateTraceSyncBarrierOpt(ARM_TSB::CSYNC, S)); |
4974 |
Operands.push_back(ARMOperand::CreateTraceSyncBarrierOpt(ARM_TSB::CSYNC, S)); |
| 4975 |
return ParseStatus::Success; |
4975 |
return ParseStatus::Success; |
| 4976 |
} |
4976 |
} |
| 4977 |
|
4977 |
|
| 4978 |
/// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options. |
4978 |
/// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options. |
| 4979 |
ParseStatus |
4979 |
ParseStatus |
| 4980 |
ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) { |
4980 |
ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) { |
| 4981 |
MCAsmParser &Parser = getParser(); |
4981 |
MCAsmParser &Parser = getParser(); |
| 4982 |
SMLoc S = Parser.getTok().getLoc(); |
4982 |
SMLoc S = Parser.getTok().getLoc(); |
| 4983 |
const AsmToken &Tok = Parser.getTok(); |
4983 |
const AsmToken &Tok = Parser.getTok(); |
| 4984 |
unsigned Opt; |
4984 |
unsigned Opt; |
| 4985 |
|
4985 |
|
| 4986 |
if (Tok.is(AsmToken::Identifier)) { |
4986 |
if (Tok.is(AsmToken::Identifier)) { |
| 4987 |
StringRef OptStr = Tok.getString(); |
4987 |
StringRef OptStr = Tok.getString(); |
| 4988 |
|
4988 |
|
| 4989 |
if (OptStr.equals_insensitive("sy")) |
4989 |
if (OptStr.equals_insensitive("sy")) |
| 4990 |
Opt = ARM_ISB::SY; |
4990 |
Opt = ARM_ISB::SY; |
| 4991 |
else |
4991 |
else |
| 4992 |
return ParseStatus::NoMatch; |
4992 |
return ParseStatus::NoMatch; |
| 4993 |
|
4993 |
|
| 4994 |
Parser.Lex(); // Eat identifier token. |
4994 |
Parser.Lex(); // Eat identifier token. |
| 4995 |
} else if (Tok.is(AsmToken::Hash) || |
4995 |
} else if (Tok.is(AsmToken::Hash) || |
| 4996 |
Tok.is(AsmToken::Dollar) || |
4996 |
Tok.is(AsmToken::Dollar) || |
| 4997 |
Tok.is(AsmToken::Integer)) { |
4997 |
Tok.is(AsmToken::Integer)) { |
| 4998 |
if (Parser.getTok().isNot(AsmToken::Integer)) |
4998 |
if (Parser.getTok().isNot(AsmToken::Integer)) |
| 4999 |
Parser.Lex(); // Eat '#' or '$'. |
4999 |
Parser.Lex(); // Eat '#' or '$'. |
| 5000 |
SMLoc Loc = Parser.getTok().getLoc(); |
5000 |
SMLoc Loc = Parser.getTok().getLoc(); |
| 5001 |
|
5001 |
|
| 5002 |
const MCExpr *ISBarrierID; |
5002 |
const MCExpr *ISBarrierID; |
| 5003 |
if (getParser().parseExpression(ISBarrierID)) |
5003 |
if (getParser().parseExpression(ISBarrierID)) |
| 5004 |
return Error(Loc, "illegal expression"); |
5004 |
return Error(Loc, "illegal expression"); |
| 5005 |
|
5005 |
|
| 5006 |
const MCConstantExpr *CE = dyn_cast(ISBarrierID); |
5006 |
const MCConstantExpr *CE = dyn_cast(ISBarrierID); |
| 5007 |
if (!CE) |
5007 |
if (!CE) |
| 5008 |
return Error(Loc, "constant expression expected"); |
5008 |
return Error(Loc, "constant expression expected"); |
| 5009 |
|
5009 |
|
| 5010 |
int Val = CE->getValue(); |
5010 |
int Val = CE->getValue(); |
| 5011 |
if (Val & ~0xf) |
5011 |
if (Val & ~0xf) |
| 5012 |
return Error(Loc, "immediate value out of range"); |
5012 |
return Error(Loc, "immediate value out of range"); |
| 5013 |
|
5013 |
|
| 5014 |
Opt = ARM_ISB::RESERVED_0 + Val; |
5014 |
Opt = ARM_ISB::RESERVED_0 + Val; |
| 5015 |
} else |
5015 |
} else |
| 5016 |
return ParseStatus::Failure; |
5016 |
return ParseStatus::Failure; |
| 5017 |
|
5017 |
|
| 5018 |
Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt( |
5018 |
Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt( |
| 5019 |
(ARM_ISB::InstSyncBOpt)Opt, S)); |
5019 |
(ARM_ISB::InstSyncBOpt)Opt, S)); |
| 5020 |
return ParseStatus::Success; |
5020 |
return ParseStatus::Success; |
| 5021 |
} |
5021 |
} |
| 5022 |
|
5022 |
|
| 5023 |
/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction. |
5023 |
/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction. |
| 5024 |
ParseStatus ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) { |
5024 |
ParseStatus ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) { |
| 5025 |
MCAsmParser &Parser = getParser(); |
5025 |
MCAsmParser &Parser = getParser(); |
| 5026 |
SMLoc S = Parser.getTok().getLoc(); |
5026 |
SMLoc S = Parser.getTok().getLoc(); |
| 5027 |
const AsmToken &Tok = Parser.getTok(); |
5027 |
const AsmToken &Tok = Parser.getTok(); |
| 5028 |
if (!Tok.is(AsmToken::Identifier)) |
5028 |
if (!Tok.is(AsmToken::Identifier)) |
| 5029 |
return ParseStatus::NoMatch; |
5029 |
return ParseStatus::NoMatch; |
| 5030 |
StringRef IFlagsStr = Tok.getString(); |
5030 |
StringRef IFlagsStr = Tok.getString(); |
| 5031 |
|
5031 |
|
| 5032 |
// An iflags string of "none" is interpreted to mean that none of the AIF |
5032 |
// An iflags string of "none" is interpreted to mean that none of the AIF |
| 5033 |
// bits are set. Not a terribly useful instruction, but a valid encoding. |
5033 |
// bits are set. Not a terribly useful instruction, but a valid encoding. |
| 5034 |
unsigned IFlags = 0; |
5034 |
unsigned IFlags = 0; |
| 5035 |
if (IFlagsStr != "none") { |
5035 |
if (IFlagsStr != "none") { |
| 5036 |
for (int i = 0, e = IFlagsStr.size(); i != e; ++i) { |
5036 |
for (int i = 0, e = IFlagsStr.size(); i != e; ++i) { |
| 5037 |
unsigned Flag = StringSwitch(IFlagsStr.substr(i, 1).lower()) |
5037 |
unsigned Flag = StringSwitch(IFlagsStr.substr(i, 1).lower()) |
| 5038 |
.Case("a", ARM_PROC::A) |
5038 |
.Case("a", ARM_PROC::A) |
| 5039 |
.Case("i", ARM_PROC::I) |
5039 |
.Case("i", ARM_PROC::I) |
| 5040 |
.Case("f", ARM_PROC::F) |
5040 |
.Case("f", ARM_PROC::F) |
| 5041 |
.Default(~0U); |
5041 |
.Default(~0U); |
| 5042 |
|
5042 |
|
| 5043 |
// If some specific iflag is already set, it means that some letter is |
5043 |
// If some specific iflag is already set, it means that some letter is |
| 5044 |
// present more than once, this is not acceptable. |
5044 |
// present more than once, this is not acceptable. |
| 5045 |
if (Flag == ~0U || (IFlags & Flag)) |
5045 |
if (Flag == ~0U || (IFlags & Flag)) |
| 5046 |
return ParseStatus::NoMatch; |
5046 |
return ParseStatus::NoMatch; |
| 5047 |
|
5047 |
|
| 5048 |
IFlags |= Flag; |
5048 |
IFlags |= Flag; |
| 5049 |
} |
5049 |
} |
| 5050 |
} |
5050 |
} |
| 5051 |
|
5051 |
|
| 5052 |
Parser.Lex(); // Eat identifier token. |
5052 |
Parser.Lex(); // Eat identifier token. |
| 5053 |
Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S)); |
5053 |
Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S)); |
| 5054 |
return ParseStatus::Success; |
5054 |
return ParseStatus::Success; |
| 5055 |
} |
5055 |
} |
| 5056 |
|
5056 |
|
| 5057 |
/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction. |
5057 |
/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction. |
| 5058 |
ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { |
5058 |
ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { |
| 5059 |
MCAsmParser &Parser = getParser(); |
5059 |
MCAsmParser &Parser = getParser(); |
| 5060 |
SMLoc S = Parser.getTok().getLoc(); |
5060 |
SMLoc S = Parser.getTok().getLoc(); |
| 5061 |
const AsmToken &Tok = Parser.getTok(); |
5061 |
const AsmToken &Tok = Parser.getTok(); |
| 5062 |
|
5062 |
|
| 5063 |
if (Tok.is(AsmToken::Integer)) { |
5063 |
if (Tok.is(AsmToken::Integer)) { |
| 5064 |
int64_t Val = Tok.getIntVal(); |
5064 |
int64_t Val = Tok.getIntVal(); |
| 5065 |
if (Val > 255 || Val < 0) { |
5065 |
if (Val > 255 || Val < 0) { |
| 5066 |
return ParseStatus::NoMatch; |
5066 |
return ParseStatus::NoMatch; |
| 5067 |
} |
5067 |
} |
| 5068 |
unsigned SYSmvalue = Val & 0xFF; |
5068 |
unsigned SYSmvalue = Val & 0xFF; |
| 5069 |
Parser.Lex(); |
5069 |
Parser.Lex(); |
| 5070 |
Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S)); |
5070 |
Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S)); |
| 5071 |
return ParseStatus::Success; |
5071 |
return ParseStatus::Success; |
| 5072 |
} |
5072 |
} |
| 5073 |
|
5073 |
|
| 5074 |
if (!Tok.is(AsmToken::Identifier)) |
5074 |
if (!Tok.is(AsmToken::Identifier)) |
| 5075 |
return ParseStatus::NoMatch; |
5075 |
return ParseStatus::NoMatch; |
| 5076 |
StringRef Mask = Tok.getString(); |
5076 |
StringRef Mask = Tok.getString(); |
| 5077 |
|
5077 |
|
| 5078 |
if (isMClass()) { |
5078 |
if (isMClass()) { |
| 5079 |
auto TheReg = ARMSysReg::lookupMClassSysRegByName(Mask.lower()); |
5079 |
auto TheReg = ARMSysReg::lookupMClassSysRegByName(Mask.lower()); |
| 5080 |
if (!TheReg || !TheReg->hasRequiredFeatures(getSTI().getFeatureBits())) |
5080 |
if (!TheReg || !TheReg->hasRequiredFeatures(getSTI().getFeatureBits())) |
| 5081 |
return ParseStatus::NoMatch; |
5081 |
return ParseStatus::NoMatch; |
| 5082 |
|
5082 |
|
| 5083 |
unsigned SYSmvalue = TheReg->Encoding & 0xFFF; |
5083 |
unsigned SYSmvalue = TheReg->Encoding & 0xFFF; |
| 5084 |
|
5084 |
|
| 5085 |
Parser.Lex(); // Eat identifier token. |
5085 |
Parser.Lex(); // Eat identifier token. |
| 5086 |
Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S)); |
5086 |
Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S)); |
| 5087 |
return ParseStatus::Success; |
5087 |
return ParseStatus::Success; |
| 5088 |
} |
5088 |
} |
| 5089 |
|
5089 |
|
| 5090 |
// Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf" |
5090 |
// Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf" |
| 5091 |
size_t Start = 0, Next = Mask.find('_'); |
5091 |
size_t Start = 0, Next = Mask.find('_'); |
| 5092 |
StringRef Flags = ""; |
5092 |
StringRef Flags = ""; |
| 5093 |
std::string SpecReg = Mask.slice(Start, Next).lower(); |
5093 |
std::string SpecReg = Mask.slice(Start, Next).lower(); |
| 5094 |
if (Next != StringRef::npos) |
5094 |
if (Next != StringRef::npos) |
| 5095 |
Flags = Mask.slice(Next+1, Mask.size()); |
5095 |
Flags = Mask.slice(Next+1, Mask.size()); |
| 5096 |
|
5096 |
|
| 5097 |
// FlagsVal contains the complete mask: |
5097 |
// FlagsVal contains the complete mask: |
| 5098 |
// 3-0: Mask |
5098 |
// 3-0: Mask |
| 5099 |
// 4: Special Reg (cpsr, apsr => 0; spsr => 1) |
5099 |
// 4: Special Reg (cpsr, apsr => 0; spsr => 1) |
| 5100 |
unsigned FlagsVal = 0; |
5100 |
unsigned FlagsVal = 0; |
| 5101 |
|
5101 |
|
| 5102 |
if (SpecReg == "apsr") { |
5102 |
if (SpecReg == "apsr") { |
| 5103 |
FlagsVal = StringSwitch(Flags) |
5103 |
FlagsVal = StringSwitch(Flags) |
| 5104 |
.Case("nzcvq", 0x8) // same as CPSR_f |
5104 |
.Case("nzcvq", 0x8) // same as CPSR_f |
| 5105 |
.Case("g", 0x4) // same as CPSR_s |
5105 |
.Case("g", 0x4) // same as CPSR_s |
| 5106 |
.Case("nzcvqg", 0xc) // same as CPSR_fs |
5106 |
.Case("nzcvqg", 0xc) // same as CPSR_fs |
| 5107 |
.Default(~0U); |
5107 |
.Default(~0U); |
| 5108 |
|
5108 |
|
| 5109 |
if (FlagsVal == ~0U) { |
5109 |
if (FlagsVal == ~0U) { |
| 5110 |
if (!Flags.empty()) |
5110 |
if (!Flags.empty()) |
| 5111 |
return ParseStatus::NoMatch; |
5111 |
return ParseStatus::NoMatch; |
| 5112 |
else |
5112 |
else |
| 5113 |
FlagsVal = 8; // No flag |
5113 |
FlagsVal = 8; // No flag |
| 5114 |
} |
5114 |
} |
| 5115 |
} else if (SpecReg == "cpsr" || SpecReg == "spsr") { |
5115 |
} else if (SpecReg == "cpsr" || SpecReg == "spsr") { |
| 5116 |
// cpsr_all is an alias for cpsr_fc, as is plain cpsr. |
5116 |
// cpsr_all is an alias for cpsr_fc, as is plain cpsr. |
| 5117 |
if (Flags == "all" || Flags == "") |
5117 |
if (Flags == "all" || Flags == "") |
| 5118 |
Flags = "fc"; |
5118 |
Flags = "fc"; |
| 5119 |
for (int i = 0, e = Flags.size(); i != e; ++i) { |
5119 |
for (int i = 0, e = Flags.size(); i != e; ++i) { |
| 5120 |
unsigned Flag = StringSwitch(Flags.substr(i, 1)) |
5120 |
unsigned Flag = StringSwitch(Flags.substr(i, 1)) |
| 5121 |
.Case("c", 1) |
5121 |
.Case("c", 1) |
| 5122 |
.Case("x", 2) |
5122 |
.Case("x", 2) |
| 5123 |
.Case("s", 4) |
5123 |
.Case("s", 4) |
| 5124 |
.Case("f", 8) |
5124 |
.Case("f", 8) |
| 5125 |
.Default(~0U); |
5125 |
.Default(~0U); |
| 5126 |
|
5126 |
|
| 5127 |
// If some specific flag is already set, it means that some letter is |
5127 |
// If some specific flag is already set, it means that some letter is |
| 5128 |
// present more than once, this is not acceptable. |
5128 |
// present more than once, this is not acceptable. |
| 5129 |
if (Flag == ~0U || (FlagsVal & Flag)) |
5129 |
if (Flag == ~0U || (FlagsVal & Flag)) |
| 5130 |
return ParseStatus::NoMatch; |
5130 |
return ParseStatus::NoMatch; |
| 5131 |
FlagsVal |= Flag; |
5131 |
FlagsVal |= Flag; |
| 5132 |
} |
5132 |
} |
| 5133 |
} else // No match for special register. |
5133 |
} else // No match for special register. |
| 5134 |
return ParseStatus::NoMatch; |
5134 |
return ParseStatus::NoMatch; |
| 5135 |
|
5135 |
|
| 5136 |
// Special register without flags is NOT equivalent to "fc" flags. |
5136 |
// Special register without flags is NOT equivalent to "fc" flags. |
| 5137 |
// NOTE: This is a divergence from gas' behavior. Uncommenting the following |
5137 |
// NOTE: This is a divergence from gas' behavior. Uncommenting the following |
| 5138 |
// two lines would enable gas compatibility at the expense of breaking |
5138 |
// two lines would enable gas compatibility at the expense of breaking |
| 5139 |
// round-tripping. |
5139 |
// round-tripping. |
| 5140 |
// |
5140 |
// |
| 5141 |
// if (!FlagsVal) |
5141 |
// if (!FlagsVal) |
| 5142 |
// FlagsVal = 0x9; |
5142 |
// FlagsVal = 0x9; |
| 5143 |
|
5143 |
|
| 5144 |
// Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1) |
5144 |
// Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1) |
| 5145 |
if (SpecReg == "spsr") |
5145 |
if (SpecReg == "spsr") |
| 5146 |
FlagsVal |= 16; |
5146 |
FlagsVal |= 16; |
| 5147 |
|
5147 |
|
| 5148 |
Parser.Lex(); // Eat identifier token. |
5148 |
Parser.Lex(); // Eat identifier token. |
| 5149 |
Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); |
5149 |
Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); |
| 5150 |
return ParseStatus::Success; |
5150 |
return ParseStatus::Success; |
| 5151 |
} |
5151 |
} |
| 5152 |
|
5152 |
|
| 5153 |
/// parseBankedRegOperand - Try to parse a banked register (e.g. "lr_irq") for |
5153 |
/// parseBankedRegOperand - Try to parse a banked register (e.g. "lr_irq") for |
| 5154 |
/// use in the MRS/MSR instructions added to support virtualization. |
5154 |
/// use in the MRS/MSR instructions added to support virtualization. |
| 5155 |
ParseStatus ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) { |
5155 |
ParseStatus ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) { |
| 5156 |
MCAsmParser &Parser = getParser(); |
5156 |
MCAsmParser &Parser = getParser(); |
| 5157 |
SMLoc S = Parser.getTok().getLoc(); |
5157 |
SMLoc S = Parser.getTok().getLoc(); |
| 5158 |
const AsmToken &Tok = Parser.getTok(); |
5158 |
const AsmToken &Tok = Parser.getTok(); |
| 5159 |
if (!Tok.is(AsmToken::Identifier)) |
5159 |
if (!Tok.is(AsmToken::Identifier)) |
| 5160 |
return ParseStatus::NoMatch; |
5160 |
return ParseStatus::NoMatch; |
| 5161 |
StringRef RegName = Tok.getString(); |
5161 |
StringRef RegName = Tok.getString(); |
| 5162 |
|
5162 |
|
| 5163 |
auto TheReg = ARMBankedReg::lookupBankedRegByName(RegName.lower()); |
5163 |
auto TheReg = ARMBankedReg::lookupBankedRegByName(RegName.lower()); |
| 5164 |
if (!TheReg) |
5164 |
if (!TheReg) |
| 5165 |
return ParseStatus::NoMatch; |
5165 |
return ParseStatus::NoMatch; |
| 5166 |
unsigned Encoding = TheReg->Encoding; |
5166 |
unsigned Encoding = TheReg->Encoding; |
| 5167 |
|
5167 |
|
| 5168 |
Parser.Lex(); // Eat identifier token. |
5168 |
Parser.Lex(); // Eat identifier token. |
| 5169 |
Operands.push_back(ARMOperand::CreateBankedReg(Encoding, S)); |
5169 |
Operands.push_back(ARMOperand::CreateBankedReg(Encoding, S)); |
| 5170 |
return ParseStatus::Success; |
5170 |
return ParseStatus::Success; |
| 5171 |
} |
5171 |
} |
| 5172 |
|
5172 |
|
| 5173 |
ParseStatus ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, |
5173 |
ParseStatus ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, |
| 5174 |
int Low, int High) { |
5174 |
int Low, int High) { |
| 5175 |
MCAsmParser &Parser = getParser(); |
5175 |
MCAsmParser &Parser = getParser(); |
| 5176 |
const AsmToken &Tok = Parser.getTok(); |
5176 |
const AsmToken &Tok = Parser.getTok(); |
| 5177 |
if (Tok.isNot(AsmToken::Identifier)) |
5177 |
if (Tok.isNot(AsmToken::Identifier)) |
| 5178 |
return Error(Parser.getTok().getLoc(), Op + " operand expected."); |
5178 |
return Error(Parser.getTok().getLoc(), Op + " operand expected."); |
| 5179 |
StringRef ShiftName = Tok.getString(); |
5179 |
StringRef ShiftName = Tok.getString(); |
| 5180 |
std::string LowerOp = Op.lower(); |
5180 |
std::string LowerOp = Op.lower(); |
| 5181 |
std::string UpperOp = Op.upper(); |
5181 |
std::string UpperOp = Op.upper(); |
| 5182 |
if (ShiftName != LowerOp && ShiftName != UpperOp) |
5182 |
if (ShiftName != LowerOp && ShiftName != UpperOp) |
| 5183 |
return Error(Parser.getTok().getLoc(), Op + " operand expected."); |
5183 |
return Error(Parser.getTok().getLoc(), Op + " operand expected."); |
| 5184 |
Parser.Lex(); // Eat shift type token. |
5184 |
Parser.Lex(); // Eat shift type token. |
| 5185 |
|
5185 |
|
| 5186 |
// There must be a '#' and a shift amount. |
5186 |
// There must be a '#' and a shift amount. |
| 5187 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
5187 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
| 5188 |
Parser.getTok().isNot(AsmToken::Dollar)) |
5188 |
Parser.getTok().isNot(AsmToken::Dollar)) |
| 5189 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
5189 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
| 5190 |
Parser.Lex(); // Eat hash token. |
5190 |
Parser.Lex(); // Eat hash token. |
| 5191 |
|
5191 |
|
| 5192 |
const MCExpr *ShiftAmount; |
5192 |
const MCExpr *ShiftAmount; |
| 5193 |
SMLoc Loc = Parser.getTok().getLoc(); |
5193 |
SMLoc Loc = Parser.getTok().getLoc(); |
| 5194 |
SMLoc EndLoc; |
5194 |
SMLoc EndLoc; |
| 5195 |
if (getParser().parseExpression(ShiftAmount, EndLoc)) |
5195 |
if (getParser().parseExpression(ShiftAmount, EndLoc)) |
| 5196 |
return Error(Loc, "illegal expression"); |
5196 |
return Error(Loc, "illegal expression"); |
| 5197 |
const MCConstantExpr *CE = dyn_cast(ShiftAmount); |
5197 |
const MCConstantExpr *CE = dyn_cast(ShiftAmount); |
| 5198 |
if (!CE) |
5198 |
if (!CE) |
| 5199 |
return Error(Loc, "constant expression expected"); |
5199 |
return Error(Loc, "constant expression expected"); |
| 5200 |
int Val = CE->getValue(); |
5200 |
int Val = CE->getValue(); |
| 5201 |
if (Val < Low || Val > High) |
5201 |
if (Val < Low || Val > High) |
| 5202 |
return Error(Loc, "immediate value out of range"); |
5202 |
return Error(Loc, "immediate value out of range"); |
| 5203 |
|
5203 |
|
| 5204 |
Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc)); |
5204 |
Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc)); |
| 5205 |
|
5205 |
|
| 5206 |
return ParseStatus::Success; |
5206 |
return ParseStatus::Success; |
| 5207 |
} |
5207 |
} |
| 5208 |
|
5208 |
|
| 5209 |
ParseStatus ARMAsmParser::parseSetEndImm(OperandVector &Operands) { |
5209 |
ParseStatus ARMAsmParser::parseSetEndImm(OperandVector &Operands) { |
| 5210 |
MCAsmParser &Parser = getParser(); |
5210 |
MCAsmParser &Parser = getParser(); |
| 5211 |
const AsmToken &Tok = Parser.getTok(); |
5211 |
const AsmToken &Tok = Parser.getTok(); |
| 5212 |
SMLoc S = Tok.getLoc(); |
5212 |
SMLoc S = Tok.getLoc(); |
| 5213 |
if (Tok.isNot(AsmToken::Identifier)) |
5213 |
if (Tok.isNot(AsmToken::Identifier)) |
| 5214 |
return Error(S, "'be' or 'le' operand expected"); |
5214 |
return Error(S, "'be' or 'le' operand expected"); |
| 5215 |
int Val = StringSwitch(Tok.getString().lower()) |
5215 |
int Val = StringSwitch(Tok.getString().lower()) |
| 5216 |
.Case("be", 1) |
5216 |
.Case("be", 1) |
| 5217 |
.Case("le", 0) |
5217 |
.Case("le", 0) |
| 5218 |
.Default(-1); |
5218 |
.Default(-1); |
| 5219 |
Parser.Lex(); // Eat the token. |
5219 |
Parser.Lex(); // Eat the token. |
| 5220 |
|
5220 |
|
| 5221 |
if (Val == -1) |
5221 |
if (Val == -1) |
| 5222 |
return Error(S, "'be' or 'le' operand expected"); |
5222 |
return Error(S, "'be' or 'le' operand expected"); |
| 5223 |
Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::create(Val, |
5223 |
Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::create(Val, |
| 5224 |
getContext()), |
5224 |
getContext()), |
| 5225 |
S, Tok.getEndLoc())); |
5225 |
S, Tok.getEndLoc())); |
| 5226 |
return ParseStatus::Success; |
5226 |
return ParseStatus::Success; |
| 5227 |
} |
5227 |
} |
| 5228 |
|
5228 |
|
| 5229 |
/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT |
5229 |
/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT |
| 5230 |
/// instructions. Legal values are: |
5230 |
/// instructions. Legal values are: |
| 5231 |
/// lsl #n 'n' in [0,31] |
5231 |
/// lsl #n 'n' in [0,31] |
| 5232 |
/// asr #n 'n' in [1,32] |
5232 |
/// asr #n 'n' in [1,32] |
| 5233 |
/// n == 32 encoded as n == 0. |
5233 |
/// n == 32 encoded as n == 0. |
| 5234 |
ParseStatus ARMAsmParser::parseShifterImm(OperandVector &Operands) { |
5234 |
ParseStatus ARMAsmParser::parseShifterImm(OperandVector &Operands) { |
| 5235 |
MCAsmParser &Parser = getParser(); |
5235 |
MCAsmParser &Parser = getParser(); |
| 5236 |
const AsmToken &Tok = Parser.getTok(); |
5236 |
const AsmToken &Tok = Parser.getTok(); |
| 5237 |
SMLoc S = Tok.getLoc(); |
5237 |
SMLoc S = Tok.getLoc(); |
| 5238 |
if (Tok.isNot(AsmToken::Identifier)) |
5238 |
if (Tok.isNot(AsmToken::Identifier)) |
| 5239 |
return Error(S, "shift operator 'asr' or 'lsl' expected"); |
5239 |
return Error(S, "shift operator 'asr' or 'lsl' expected"); |
| 5240 |
StringRef ShiftName = Tok.getString(); |
5240 |
StringRef ShiftName = Tok.getString(); |
| 5241 |
bool isASR; |
5241 |
bool isASR; |
| 5242 |
if (ShiftName == "lsl" || ShiftName == "LSL") |
5242 |
if (ShiftName == "lsl" || ShiftName == "LSL") |
| 5243 |
isASR = false; |
5243 |
isASR = false; |
| 5244 |
else if (ShiftName == "asr" || ShiftName == "ASR") |
5244 |
else if (ShiftName == "asr" || ShiftName == "ASR") |
| 5245 |
isASR = true; |
5245 |
isASR = true; |
| 5246 |
else |
5246 |
else |
| 5247 |
return Error(S, "shift operator 'asr' or 'lsl' expected"); |
5247 |
return Error(S, "shift operator 'asr' or 'lsl' expected"); |
| 5248 |
Parser.Lex(); // Eat the operator. |
5248 |
Parser.Lex(); // Eat the operator. |
| 5249 |
|
5249 |
|
| 5250 |
// A '#' and a shift amount. |
5250 |
// A '#' and a shift amount. |
| 5251 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
5251 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
| 5252 |
Parser.getTok().isNot(AsmToken::Dollar)) |
5252 |
Parser.getTok().isNot(AsmToken::Dollar)) |
| 5253 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
5253 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
| 5254 |
Parser.Lex(); // Eat hash token. |
5254 |
Parser.Lex(); // Eat hash token. |
| 5255 |
SMLoc ExLoc = Parser.getTok().getLoc(); |
5255 |
SMLoc ExLoc = Parser.getTok().getLoc(); |
| 5256 |
|
5256 |
|
| 5257 |
const MCExpr *ShiftAmount; |
5257 |
const MCExpr *ShiftAmount; |
| 5258 |
SMLoc EndLoc; |
5258 |
SMLoc EndLoc; |
| 5259 |
if (getParser().parseExpression(ShiftAmount, EndLoc)) |
5259 |
if (getParser().parseExpression(ShiftAmount, EndLoc)) |
| 5260 |
return Error(ExLoc, "malformed shift expression"); |
5260 |
return Error(ExLoc, "malformed shift expression"); |
| 5261 |
const MCConstantExpr *CE = dyn_cast(ShiftAmount); |
5261 |
const MCConstantExpr *CE = dyn_cast(ShiftAmount); |
| 5262 |
if (!CE) |
5262 |
if (!CE) |
| 5263 |
return Error(ExLoc, "shift amount must be an immediate"); |
5263 |
return Error(ExLoc, "shift amount must be an immediate"); |
| 5264 |
|
5264 |
|
| 5265 |
int64_t Val = CE->getValue(); |
5265 |
int64_t Val = CE->getValue(); |
| 5266 |
if (isASR) { |
5266 |
if (isASR) { |
| 5267 |
// Shift amount must be in [1,32] |
5267 |
// Shift amount must be in [1,32] |
| 5268 |
if (Val < 1 || Val > 32) |
5268 |
if (Val < 1 || Val > 32) |
| 5269 |
return Error(ExLoc, "'asr' shift amount must be in range [1,32]"); |
5269 |
return Error(ExLoc, "'asr' shift amount must be in range [1,32]"); |
| 5270 |
// asr #32 encoded as asr #0, but is not allowed in Thumb2 mode. |
5270 |
// asr #32 encoded as asr #0, but is not allowed in Thumb2 mode. |
| 5271 |
if (isThumb() && Val == 32) |
5271 |
if (isThumb() && Val == 32) |
| 5272 |
return Error(ExLoc, "'asr #32' shift amount not allowed in Thumb mode"); |
5272 |
return Error(ExLoc, "'asr #32' shift amount not allowed in Thumb mode"); |
| 5273 |
if (Val == 32) Val = 0; |
5273 |
if (Val == 32) Val = 0; |
| 5274 |
} else { |
5274 |
} else { |
| 5275 |
// Shift amount must be in [1,32] |
5275 |
// Shift amount must be in [1,32] |
| 5276 |
if (Val < 0 || Val > 31) |
5276 |
if (Val < 0 || Val > 31) |
| 5277 |
return Error(ExLoc, "'lsr' shift amount must be in range [0,31]"); |
5277 |
return Error(ExLoc, "'lsr' shift amount must be in range [0,31]"); |
| 5278 |
} |
5278 |
} |
| 5279 |
|
5279 |
|
| 5280 |
Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc)); |
5280 |
Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc)); |
| 5281 |
|
5281 |
|
| 5282 |
return ParseStatus::Success; |
5282 |
return ParseStatus::Success; |
| 5283 |
} |
5283 |
} |
| 5284 |
|
5284 |
|
| 5285 |
/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family |
5285 |
/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family |
| 5286 |
/// of instructions. Legal values are: |
5286 |
/// of instructions. Legal values are: |
| 5287 |
/// ror #n 'n' in {0, 8, 16, 24} |
5287 |
/// ror #n 'n' in {0, 8, 16, 24} |
| 5288 |
ParseStatus ARMAsmParser::parseRotImm(OperandVector &Operands) { |
5288 |
ParseStatus ARMAsmParser::parseRotImm(OperandVector &Operands) { |
| 5289 |
MCAsmParser &Parser = getParser(); |
5289 |
MCAsmParser &Parser = getParser(); |
| 5290 |
const AsmToken &Tok = Parser.getTok(); |
5290 |
const AsmToken &Tok = Parser.getTok(); |
| 5291 |
SMLoc S = Tok.getLoc(); |
5291 |
SMLoc S = Tok.getLoc(); |
| 5292 |
if (Tok.isNot(AsmToken::Identifier)) |
5292 |
if (Tok.isNot(AsmToken::Identifier)) |
| 5293 |
return ParseStatus::NoMatch; |
5293 |
return ParseStatus::NoMatch; |
| 5294 |
StringRef ShiftName = Tok.getString(); |
5294 |
StringRef ShiftName = Tok.getString(); |
| 5295 |
if (ShiftName != "ror" && ShiftName != "ROR") |
5295 |
if (ShiftName != "ror" && ShiftName != "ROR") |
| 5296 |
return ParseStatus::NoMatch; |
5296 |
return ParseStatus::NoMatch; |
| 5297 |
Parser.Lex(); // Eat the operator. |
5297 |
Parser.Lex(); // Eat the operator. |
| 5298 |
|
5298 |
|
| 5299 |
// A '#' and a rotate amount. |
5299 |
// A '#' and a rotate amount. |
| 5300 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
5300 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
| 5301 |
Parser.getTok().isNot(AsmToken::Dollar)) |
5301 |
Parser.getTok().isNot(AsmToken::Dollar)) |
| 5302 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
5302 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
| 5303 |
Parser.Lex(); // Eat hash token. |
5303 |
Parser.Lex(); // Eat hash token. |
| 5304 |
SMLoc ExLoc = Parser.getTok().getLoc(); |
5304 |
SMLoc ExLoc = Parser.getTok().getLoc(); |
| 5305 |
|
5305 |
|
| 5306 |
const MCExpr *ShiftAmount; |
5306 |
const MCExpr *ShiftAmount; |
| 5307 |
SMLoc EndLoc; |
5307 |
SMLoc EndLoc; |
| 5308 |
if (getParser().parseExpression(ShiftAmount, EndLoc)) |
5308 |
if (getParser().parseExpression(ShiftAmount, EndLoc)) |
| 5309 |
return Error(ExLoc, "malformed rotate expression"); |
5309 |
return Error(ExLoc, "malformed rotate expression"); |
| 5310 |
const MCConstantExpr *CE = dyn_cast(ShiftAmount); |
5310 |
const MCConstantExpr *CE = dyn_cast(ShiftAmount); |
| 5311 |
if (!CE) |
5311 |
if (!CE) |
| 5312 |
return Error(ExLoc, "rotate amount must be an immediate"); |
5312 |
return Error(ExLoc, "rotate amount must be an immediate"); |
| 5313 |
|
5313 |
|
| 5314 |
int64_t Val = CE->getValue(); |
5314 |
int64_t Val = CE->getValue(); |
| 5315 |
// Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension) |
5315 |
// Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension) |
| 5316 |
// normally, zero is represented in asm by omitting the rotate operand |
5316 |
// normally, zero is represented in asm by omitting the rotate operand |
| 5317 |
// entirely. |
5317 |
// entirely. |
| 5318 |
if (Val != 8 && Val != 16 && Val != 24 && Val != 0) |
5318 |
if (Val != 8 && Val != 16 && Val != 24 && Val != 0) |
| 5319 |
return Error(ExLoc, "'ror' rotate amount must be 8, 16, or 24"); |
5319 |
return Error(ExLoc, "'ror' rotate amount must be 8, 16, or 24"); |
| 5320 |
|
5320 |
|
| 5321 |
Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc)); |
5321 |
Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc)); |
| 5322 |
|
5322 |
|
| 5323 |
return ParseStatus::Success; |
5323 |
return ParseStatus::Success; |
| 5324 |
} |
5324 |
} |
| 5325 |
|
5325 |
|
| 5326 |
ParseStatus ARMAsmParser::parseModImm(OperandVector &Operands) { |
5326 |
ParseStatus ARMAsmParser::parseModImm(OperandVector &Operands) { |
| 5327 |
MCAsmParser &Parser = getParser(); |
5327 |
MCAsmParser &Parser = getParser(); |
| 5328 |
MCAsmLexer &Lexer = getLexer(); |
5328 |
MCAsmLexer &Lexer = getLexer(); |
| 5329 |
int64_t Imm1, Imm2; |
5329 |
int64_t Imm1, Imm2; |
| 5330 |
|
5330 |
|
| 5331 |
SMLoc S = Parser.getTok().getLoc(); |
5331 |
SMLoc S = Parser.getTok().getLoc(); |
| 5332 |
|
5332 |
|
| 5333 |
// 1) A mod_imm operand can appear in the place of a register name: |
5333 |
// 1) A mod_imm operand can appear in the place of a register name: |
| 5334 |
// add r0, #mod_imm |
5334 |
// add r0, #mod_imm |
| 5335 |
// add r0, r0, #mod_imm |
5335 |
// add r0, r0, #mod_imm |
| 5336 |
// to correctly handle the latter, we bail out as soon as we see an |
5336 |
// to correctly handle the latter, we bail out as soon as we see an |
| 5337 |
// identifier. |
5337 |
// identifier. |
| 5338 |
// |
5338 |
// |
| 5339 |
// 2) Similarly, we do not want to parse into complex operands: |
5339 |
// 2) Similarly, we do not want to parse into complex operands: |
| 5340 |
// mov r0, #mod_imm |
5340 |
// mov r0, #mod_imm |
| 5341 |
// mov r0, :lower16:(_foo) |
5341 |
// mov r0, :lower16:(_foo) |
| 5342 |
if (Parser.getTok().is(AsmToken::Identifier) || |
5342 |
if (Parser.getTok().is(AsmToken::Identifier) || |
| 5343 |
Parser.getTok().is(AsmToken::Colon)) |
5343 |
Parser.getTok().is(AsmToken::Colon)) |
| 5344 |
return ParseStatus::NoMatch; |
5344 |
return ParseStatus::NoMatch; |
| 5345 |
|
5345 |
|
| 5346 |
// Hash (dollar) is optional as per the ARMARM |
5346 |
// Hash (dollar) is optional as per the ARMARM |
| 5347 |
if (Parser.getTok().is(AsmToken::Hash) || |
5347 |
if (Parser.getTok().is(AsmToken::Hash) || |
| 5348 |
Parser.getTok().is(AsmToken::Dollar)) { |
5348 |
Parser.getTok().is(AsmToken::Dollar)) { |
| 5349 |
// Avoid parsing into complex operands (#:) |
5349 |
// Avoid parsing into complex operands (#:) |
| 5350 |
if (Lexer.peekTok().is(AsmToken::Colon)) |
5350 |
if (Lexer.peekTok().is(AsmToken::Colon)) |
| 5351 |
return ParseStatus::NoMatch; |
5351 |
return ParseStatus::NoMatch; |
| 5352 |
|
5352 |
|
| 5353 |
// Eat the hash (dollar) |
5353 |
// Eat the hash (dollar) |
| 5354 |
Parser.Lex(); |
5354 |
Parser.Lex(); |
| 5355 |
} |
5355 |
} |
| 5356 |
|
5356 |
|
| 5357 |
SMLoc Sx1, Ex1; |
5357 |
SMLoc Sx1, Ex1; |
| 5358 |
Sx1 = Parser.getTok().getLoc(); |
5358 |
Sx1 = Parser.getTok().getLoc(); |
| 5359 |
const MCExpr *Imm1Exp; |
5359 |
const MCExpr *Imm1Exp; |
| 5360 |
if (getParser().parseExpression(Imm1Exp, Ex1)) |
5360 |
if (getParser().parseExpression(Imm1Exp, Ex1)) |
| 5361 |
return Error(Sx1, "malformed expression"); |
5361 |
return Error(Sx1, "malformed expression"); |
| 5362 |
|
5362 |
|
| 5363 |
const MCConstantExpr *CE = dyn_cast(Imm1Exp); |
5363 |
const MCConstantExpr *CE = dyn_cast(Imm1Exp); |
| 5364 |
|
5364 |
|
| 5365 |
if (CE) { |
5365 |
if (CE) { |
| 5366 |
// Immediate must fit within 32-bits |
5366 |
// Immediate must fit within 32-bits |
| 5367 |
Imm1 = CE->getValue(); |
5367 |
Imm1 = CE->getValue(); |
| 5368 |
int Enc = ARM_AM::getSOImmVal(Imm1); |
5368 |
int Enc = ARM_AM::getSOImmVal(Imm1); |
| 5369 |
if (Enc != -1 && Parser.getTok().is(AsmToken::EndOfStatement)) { |
5369 |
if (Enc != -1 && Parser.getTok().is(AsmToken::EndOfStatement)) { |
| 5370 |
// We have a match! |
5370 |
// We have a match! |
| 5371 |
Operands.push_back(ARMOperand::CreateModImm((Enc & 0xFF), |
5371 |
Operands.push_back(ARMOperand::CreateModImm((Enc & 0xFF), |
| 5372 |
(Enc & 0xF00) >> 7, |
5372 |
(Enc & 0xF00) >> 7, |
| 5373 |
Sx1, Ex1)); |
5373 |
Sx1, Ex1)); |
| 5374 |
return ParseStatus::Success; |
5374 |
return ParseStatus::Success; |
| 5375 |
} |
5375 |
} |
| 5376 |
|
5376 |
|
| 5377 |
// We have parsed an immediate which is not for us, fallback to a plain |
5377 |
// We have parsed an immediate which is not for us, fallback to a plain |
| 5378 |
// immediate. This can happen for instruction aliases. For an example, |
5378 |
// immediate. This can happen for instruction aliases. For an example, |
| 5379 |
// ARMInstrInfo.td defines the alias [mov <-> mvn] which can transform |
5379 |
// ARMInstrInfo.td defines the alias [mov <-> mvn] which can transform |
| 5380 |
// a mov (mvn) with a mod_imm_neg/mod_imm_not operand into the opposite |
5380 |
// a mov (mvn) with a mod_imm_neg/mod_imm_not operand into the opposite |
| 5381 |
// instruction with a mod_imm operand. The alias is defined such that the |
5381 |
// instruction with a mod_imm operand. The alias is defined such that the |
| 5382 |
// parser method is shared, that's why we have to do this here. |
5382 |
// parser method is shared, that's why we have to do this here. |
| 5383 |
if (Parser.getTok().is(AsmToken::EndOfStatement)) { |
5383 |
if (Parser.getTok().is(AsmToken::EndOfStatement)) { |
| 5384 |
Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1)); |
5384 |
Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1)); |
| 5385 |
return ParseStatus::Success; |
5385 |
return ParseStatus::Success; |
| 5386 |
} |
5386 |
} |
| 5387 |
} else { |
5387 |
} else { |
| 5388 |
// Operands like #(l1 - l2) can only be evaluated at a later stage (via an |
5388 |
// Operands like #(l1 - l2) can only be evaluated at a later stage (via an |
| 5389 |
// MCFixup). Fallback to a plain immediate. |
5389 |
// MCFixup). Fallback to a plain immediate. |
| 5390 |
Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1)); |
5390 |
Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1)); |
| 5391 |
return ParseStatus::Success; |
5391 |
return ParseStatus::Success; |
| 5392 |
} |
5392 |
} |
| 5393 |
|
5393 |
|
| 5394 |
// From this point onward, we expect the input to be a (#bits, #rot) pair |
5394 |
// From this point onward, we expect the input to be a (#bits, #rot) pair |
| 5395 |
if (Parser.getTok().isNot(AsmToken::Comma)) |
5395 |
if (Parser.getTok().isNot(AsmToken::Comma)) |
| 5396 |
return Error(Sx1, |
5396 |
return Error(Sx1, |
| 5397 |
"expected modified immediate operand: #[0, 255], #even[0-30]"); |
5397 |
"expected modified immediate operand: #[0, 255], #even[0-30]"); |
| 5398 |
|
5398 |
|
| 5399 |
if (Imm1 & ~0xFF) |
5399 |
if (Imm1 & ~0xFF) |
| 5400 |
return Error(Sx1, "immediate operand must a number in the range [0, 255]"); |
5400 |
return Error(Sx1, "immediate operand must a number in the range [0, 255]"); |
| 5401 |
|
5401 |
|
| 5402 |
// Eat the comma |
5402 |
// Eat the comma |
| 5403 |
Parser.Lex(); |
5403 |
Parser.Lex(); |
| 5404 |
|
5404 |
|
| 5405 |
// Repeat for #rot |
5405 |
// Repeat for #rot |
| 5406 |
SMLoc Sx2, Ex2; |
5406 |
SMLoc Sx2, Ex2; |
| 5407 |
Sx2 = Parser.getTok().getLoc(); |
5407 |
Sx2 = Parser.getTok().getLoc(); |
| 5408 |
|
5408 |
|
| 5409 |
// Eat the optional hash (dollar) |
5409 |
// Eat the optional hash (dollar) |
| 5410 |
if (Parser.getTok().is(AsmToken::Hash) || |
5410 |
if (Parser.getTok().is(AsmToken::Hash) || |
| 5411 |
Parser.getTok().is(AsmToken::Dollar)) |
5411 |
Parser.getTok().is(AsmToken::Dollar)) |
| 5412 |
Parser.Lex(); |
5412 |
Parser.Lex(); |
| 5413 |
|
5413 |
|
| 5414 |
const MCExpr *Imm2Exp; |
5414 |
const MCExpr *Imm2Exp; |
| 5415 |
if (getParser().parseExpression(Imm2Exp, Ex2)) |
5415 |
if (getParser().parseExpression(Imm2Exp, Ex2)) |
| 5416 |
return Error(Sx2, "malformed expression"); |
5416 |
return Error(Sx2, "malformed expression"); |
| 5417 |
|
5417 |
|
| 5418 |
CE = dyn_cast(Imm2Exp); |
5418 |
CE = dyn_cast(Imm2Exp); |
| 5419 |
|
5419 |
|
| 5420 |
if (CE) { |
5420 |
if (CE) { |
| 5421 |
Imm2 = CE->getValue(); |
5421 |
Imm2 = CE->getValue(); |
| 5422 |
if (!(Imm2 & ~0x1E)) { |
5422 |
if (!(Imm2 & ~0x1E)) { |
| 5423 |
// We have a match! |
5423 |
// We have a match! |
| 5424 |
Operands.push_back(ARMOperand::CreateModImm(Imm1, Imm2, S, Ex2)); |
5424 |
Operands.push_back(ARMOperand::CreateModImm(Imm1, Imm2, S, Ex2)); |
| 5425 |
return ParseStatus::Success; |
5425 |
return ParseStatus::Success; |
| 5426 |
} |
5426 |
} |
| 5427 |
return Error(Sx2, |
5427 |
return Error(Sx2, |
| 5428 |
"immediate operand must an even number in the range [0, 30]"); |
5428 |
"immediate operand must an even number in the range [0, 30]"); |
| 5429 |
} else { |
5429 |
} else { |
| 5430 |
return Error(Sx2, "constant expression expected"); |
5430 |
return Error(Sx2, "constant expression expected"); |
| 5431 |
} |
5431 |
} |
| 5432 |
} |
5432 |
} |
| 5433 |
|
5433 |
|
| 5434 |
ParseStatus ARMAsmParser::parseBitfield(OperandVector &Operands) { |
5434 |
ParseStatus ARMAsmParser::parseBitfield(OperandVector &Operands) { |
| 5435 |
MCAsmParser &Parser = getParser(); |
5435 |
MCAsmParser &Parser = getParser(); |
| 5436 |
SMLoc S = Parser.getTok().getLoc(); |
5436 |
SMLoc S = Parser.getTok().getLoc(); |
| 5437 |
// The bitfield descriptor is really two operands, the LSB and the width. |
5437 |
// The bitfield descriptor is really two operands, the LSB and the width. |
| 5438 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
5438 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
| 5439 |
Parser.getTok().isNot(AsmToken::Dollar)) |
5439 |
Parser.getTok().isNot(AsmToken::Dollar)) |
| 5440 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
5440 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
| 5441 |
Parser.Lex(); // Eat hash token. |
5441 |
Parser.Lex(); // Eat hash token. |
| 5442 |
|
5442 |
|
| 5443 |
const MCExpr *LSBExpr; |
5443 |
const MCExpr *LSBExpr; |
| 5444 |
SMLoc E = Parser.getTok().getLoc(); |
5444 |
SMLoc E = Parser.getTok().getLoc(); |
| 5445 |
if (getParser().parseExpression(LSBExpr)) |
5445 |
if (getParser().parseExpression(LSBExpr)) |
| 5446 |
return Error(E, "malformed immediate expression"); |
5446 |
return Error(E, "malformed immediate expression"); |
| 5447 |
const MCConstantExpr *CE = dyn_cast(LSBExpr); |
5447 |
const MCConstantExpr *CE = dyn_cast(LSBExpr); |
| 5448 |
if (!CE) |
5448 |
if (!CE) |
| 5449 |
return Error(E, "'lsb' operand must be an immediate"); |
5449 |
return Error(E, "'lsb' operand must be an immediate"); |
| 5450 |
|
5450 |
|
| 5451 |
int64_t LSB = CE->getValue(); |
5451 |
int64_t LSB = CE->getValue(); |
| 5452 |
// The LSB must be in the range [0,31] |
5452 |
// The LSB must be in the range [0,31] |
| 5453 |
if (LSB < 0 || LSB > 31) |
5453 |
if (LSB < 0 || LSB > 31) |
| 5454 |
return Error(E, "'lsb' operand must be in the range [0,31]"); |
5454 |
return Error(E, "'lsb' operand must be in the range [0,31]"); |
| 5455 |
E = Parser.getTok().getLoc(); |
5455 |
E = Parser.getTok().getLoc(); |
| 5456 |
|
5456 |
|
| 5457 |
// Expect another immediate operand. |
5457 |
// Expect another immediate operand. |
| 5458 |
if (Parser.getTok().isNot(AsmToken::Comma)) |
5458 |
if (Parser.getTok().isNot(AsmToken::Comma)) |
| 5459 |
return Error(Parser.getTok().getLoc(), "too few operands"); |
5459 |
return Error(Parser.getTok().getLoc(), "too few operands"); |
| 5460 |
Parser.Lex(); // Eat hash token. |
5460 |
Parser.Lex(); // Eat hash token. |
| 5461 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
5461 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
| 5462 |
Parser.getTok().isNot(AsmToken::Dollar)) |
5462 |
Parser.getTok().isNot(AsmToken::Dollar)) |
| 5463 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
5463 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
| 5464 |
Parser.Lex(); // Eat hash token. |
5464 |
Parser.Lex(); // Eat hash token. |
| 5465 |
|
5465 |
|
| 5466 |
const MCExpr *WidthExpr; |
5466 |
const MCExpr *WidthExpr; |
| 5467 |
SMLoc EndLoc; |
5467 |
SMLoc EndLoc; |
| 5468 |
if (getParser().parseExpression(WidthExpr, EndLoc)) |
5468 |
if (getParser().parseExpression(WidthExpr, EndLoc)) |
| 5469 |
return Error(E, "malformed immediate expression"); |
5469 |
return Error(E, "malformed immediate expression"); |
| 5470 |
CE = dyn_cast(WidthExpr); |
5470 |
CE = dyn_cast(WidthExpr); |
| 5471 |
if (!CE) |
5471 |
if (!CE) |
| 5472 |
return Error(E, "'width' operand must be an immediate"); |
5472 |
return Error(E, "'width' operand must be an immediate"); |
| 5473 |
|
5473 |
|
| 5474 |
int64_t Width = CE->getValue(); |
5474 |
int64_t Width = CE->getValue(); |
| 5475 |
// The LSB must be in the range [1,32-lsb] |
5475 |
// The LSB must be in the range [1,32-lsb] |
| 5476 |
if (Width < 1 || Width > 32 - LSB) |
5476 |
if (Width < 1 || Width > 32 - LSB) |
| 5477 |
return Error(E, "'width' operand must be in the range [1,32-lsb]"); |
5477 |
return Error(E, "'width' operand must be in the range [1,32-lsb]"); |
| 5478 |
|
5478 |
|
| 5479 |
Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc)); |
5479 |
Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc)); |
| 5480 |
|
5480 |
|
| 5481 |
return ParseStatus::Success; |
5481 |
return ParseStatus::Success; |
| 5482 |
} |
5482 |
} |
| 5483 |
|
5483 |
|
| 5484 |
ParseStatus ARMAsmParser::parsePostIdxReg(OperandVector &Operands) { |
5484 |
ParseStatus ARMAsmParser::parsePostIdxReg(OperandVector &Operands) { |
| 5485 |
// Check for a post-index addressing register operand. Specifically: |
5485 |
// Check for a post-index addressing register operand. Specifically: |
| 5486 |
// postidx_reg := '+' register {, shift} |
5486 |
// postidx_reg := '+' register {, shift} |
| 5487 |
// | '-' register {, shift} |
5487 |
// | '-' register {, shift} |
| 5488 |
// | register {, shift} |
5488 |
// | register {, shift} |
| 5489 |
|
5489 |
|
| 5490 |
// This method must return ParseStatus::NoMatch without consuming any tokens |
5490 |
// This method must return ParseStatus::NoMatch without consuming any tokens |
| 5491 |
// in the case where there is no match, as other alternatives take other |
5491 |
// in the case where there is no match, as other alternatives take other |
| 5492 |
// parse methods. |
5492 |
// parse methods. |
| 5493 |
MCAsmParser &Parser = getParser(); |
5493 |
MCAsmParser &Parser = getParser(); |
| 5494 |
AsmToken Tok = Parser.getTok(); |
5494 |
AsmToken Tok = Parser.getTok(); |
| 5495 |
SMLoc S = Tok.getLoc(); |
5495 |
SMLoc S = Tok.getLoc(); |
| 5496 |
bool haveEaten = false; |
5496 |
bool haveEaten = false; |
| 5497 |
bool isAdd = true; |
5497 |
bool isAdd = true; |
| 5498 |
if (Tok.is(AsmToken::Plus)) { |
5498 |
if (Tok.is(AsmToken::Plus)) { |
| 5499 |
Parser.Lex(); // Eat the '+' token. |
5499 |
Parser.Lex(); // Eat the '+' token. |
| 5500 |
haveEaten = true; |
5500 |
haveEaten = true; |
| 5501 |
} else if (Tok.is(AsmToken::Minus)) { |
5501 |
} else if (Tok.is(AsmToken::Minus)) { |
| 5502 |
Parser.Lex(); // Eat the '-' token. |
5502 |
Parser.Lex(); // Eat the '-' token. |
| 5503 |
isAdd = false; |
5503 |
isAdd = false; |
| 5504 |
haveEaten = true; |
5504 |
haveEaten = true; |
| 5505 |
} |
5505 |
} |
| 5506 |
|
5506 |
|
| 5507 |
SMLoc E = Parser.getTok().getEndLoc(); |
5507 |
SMLoc E = Parser.getTok().getEndLoc(); |
| 5508 |
int Reg = tryParseRegister(); |
5508 |
int Reg = tryParseRegister(); |
| 5509 |
if (Reg == -1) { |
5509 |
if (Reg == -1) { |
| 5510 |
if (!haveEaten) |
5510 |
if (!haveEaten) |
| 5511 |
return ParseStatus::NoMatch; |
5511 |
return ParseStatus::NoMatch; |
| 5512 |
return Error(Parser.getTok().getLoc(), "register expected"); |
5512 |
return Error(Parser.getTok().getLoc(), "register expected"); |
| 5513 |
} |
5513 |
} |
| 5514 |
|
5514 |
|
| 5515 |
ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift; |
5515 |
ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift; |
| 5516 |
unsigned ShiftImm = 0; |
5516 |
unsigned ShiftImm = 0; |
| 5517 |
if (Parser.getTok().is(AsmToken::Comma)) { |
5517 |
if (Parser.getTok().is(AsmToken::Comma)) { |
| 5518 |
Parser.Lex(); // Eat the ','. |
5518 |
Parser.Lex(); // Eat the ','. |
| 5519 |
if (parseMemRegOffsetShift(ShiftTy, ShiftImm)) |
5519 |
if (parseMemRegOffsetShift(ShiftTy, ShiftImm)) |
| 5520 |
return ParseStatus::Failure; |
5520 |
return ParseStatus::Failure; |
| 5521 |
|
5521 |
|
| 5522 |
// FIXME: Only approximates end...may include intervening whitespace. |
5522 |
// FIXME: Only approximates end...may include intervening whitespace. |
| 5523 |
E = Parser.getTok().getLoc(); |
5523 |
E = Parser.getTok().getLoc(); |
| 5524 |
} |
5524 |
} |
| 5525 |
|
5525 |
|
| 5526 |
Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy, |
5526 |
Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy, |
| 5527 |
ShiftImm, S, E)); |
5527 |
ShiftImm, S, E)); |
| 5528 |
|
5528 |
|
| 5529 |
return ParseStatus::Success; |
5529 |
return ParseStatus::Success; |
| 5530 |
} |
5530 |
} |
| 5531 |
|
5531 |
|
| 5532 |
ParseStatus ARMAsmParser::parseAM3Offset(OperandVector &Operands) { |
5532 |
ParseStatus ARMAsmParser::parseAM3Offset(OperandVector &Operands) { |
| 5533 |
// Check for a post-index addressing register operand. Specifically: |
5533 |
// Check for a post-index addressing register operand. Specifically: |
| 5534 |
// am3offset := '+' register |
5534 |
// am3offset := '+' register |
| 5535 |
// | '-' register |
5535 |
// | '-' register |
| 5536 |
// | register |
5536 |
// | register |
| 5537 |
// | # imm |
5537 |
// | # imm |
| 5538 |
// | # + imm |
5538 |
// | # + imm |
| 5539 |
// | # - imm |
5539 |
// | # - imm |
| 5540 |
|
5540 |
|
| 5541 |
// This method must return ParseStatus::NoMatch without consuming any tokens |
5541 |
// This method must return ParseStatus::NoMatch without consuming any tokens |
| 5542 |
// in the case where there is no match, as other alternatives take other |
5542 |
// in the case where there is no match, as other alternatives take other |
| 5543 |
// parse methods. |
5543 |
// parse methods. |
| 5544 |
MCAsmParser &Parser = getParser(); |
5544 |
MCAsmParser &Parser = getParser(); |
| 5545 |
AsmToken Tok = Parser.getTok(); |
5545 |
AsmToken Tok = Parser.getTok(); |
| 5546 |
SMLoc S = Tok.getLoc(); |
5546 |
SMLoc S = Tok.getLoc(); |
| 5547 |
|
5547 |
|
| 5548 |
// Do immediates first, as we always parse those if we have a '#'. |
5548 |
// Do immediates first, as we always parse those if we have a '#'. |
| 5549 |
if (Parser.getTok().is(AsmToken::Hash) || |
5549 |
if (Parser.getTok().is(AsmToken::Hash) || |
| 5550 |
Parser.getTok().is(AsmToken::Dollar)) { |
5550 |
Parser.getTok().is(AsmToken::Dollar)) { |
| 5551 |
Parser.Lex(); // Eat '#' or '$'. |
5551 |
Parser.Lex(); // Eat '#' or '$'. |
| 5552 |
// Explicitly look for a '-', as we need to encode negative zero |
5552 |
// Explicitly look for a '-', as we need to encode negative zero |
| 5553 |
// differently. |
5553 |
// differently. |
| 5554 |
bool isNegative = Parser.getTok().is(AsmToken::Minus); |
5554 |
bool isNegative = Parser.getTok().is(AsmToken::Minus); |
| 5555 |
const MCExpr *Offset; |
5555 |
const MCExpr *Offset; |
| 5556 |
SMLoc E; |
5556 |
SMLoc E; |
| 5557 |
if (getParser().parseExpression(Offset, E)) |
5557 |
if (getParser().parseExpression(Offset, E)) |
| 5558 |
return ParseStatus::Failure; |
5558 |
return ParseStatus::Failure; |
| 5559 |
const MCConstantExpr *CE = dyn_cast(Offset); |
5559 |
const MCConstantExpr *CE = dyn_cast(Offset); |
| 5560 |
if (!CE) |
5560 |
if (!CE) |
| 5561 |
return Error(S, "constant expression expected"); |
5561 |
return Error(S, "constant expression expected"); |
| 5562 |
// Negative zero is encoded as the flag value |
5562 |
// Negative zero is encoded as the flag value |
| 5563 |
// std::numeric_limits::min(). |
5563 |
// std::numeric_limits::min(). |
| 5564 |
int32_t Val = CE->getValue(); |
5564 |
int32_t Val = CE->getValue(); |
| 5565 |
if (isNegative && Val == 0) |
5565 |
if (isNegative && Val == 0) |
| 5566 |
Val = std::numeric_limits::min(); |
5566 |
Val = std::numeric_limits::min(); |
| 5567 |
|
5567 |
|
| 5568 |
Operands.push_back( |
5568 |
Operands.push_back( |
| 5569 |
ARMOperand::CreateImm(MCConstantExpr::create(Val, getContext()), S, E)); |
5569 |
ARMOperand::CreateImm(MCConstantExpr::create(Val, getContext()), S, E)); |
| 5570 |
|
5570 |
|
| 5571 |
return ParseStatus::Success; |
5571 |
return ParseStatus::Success; |
| 5572 |
} |
5572 |
} |
| 5573 |
|
5573 |
|
| 5574 |
bool haveEaten = false; |
5574 |
bool haveEaten = false; |
| 5575 |
bool isAdd = true; |
5575 |
bool isAdd = true; |
| 5576 |
if (Tok.is(AsmToken::Plus)) { |
5576 |
if (Tok.is(AsmToken::Plus)) { |
| 5577 |
Parser.Lex(); // Eat the '+' token. |
5577 |
Parser.Lex(); // Eat the '+' token. |
| 5578 |
haveEaten = true; |
5578 |
haveEaten = true; |
| 5579 |
} else if (Tok.is(AsmToken::Minus)) { |
5579 |
} else if (Tok.is(AsmToken::Minus)) { |
| 5580 |
Parser.Lex(); // Eat the '-' token. |
5580 |
Parser.Lex(); // Eat the '-' token. |
| 5581 |
isAdd = false; |
5581 |
isAdd = false; |
| 5582 |
haveEaten = true; |
5582 |
haveEaten = true; |
| 5583 |
} |
5583 |
} |
| 5584 |
|
5584 |
|
| 5585 |
Tok = Parser.getTok(); |
5585 |
Tok = Parser.getTok(); |
| 5586 |
int Reg = tryParseRegister(); |
5586 |
int Reg = tryParseRegister(); |
| 5587 |
if (Reg == -1) { |
5587 |
if (Reg == -1) { |
| 5588 |
if (!haveEaten) |
5588 |
if (!haveEaten) |
| 5589 |
return ParseStatus::NoMatch; |
5589 |
return ParseStatus::NoMatch; |
| 5590 |
return Error(Tok.getLoc(), "register expected"); |
5590 |
return Error(Tok.getLoc(), "register expected"); |
| 5591 |
} |
5591 |
} |
| 5592 |
|
5592 |
|
| 5593 |
Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift, |
5593 |
Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift, |
| 5594 |
0, S, Tok.getEndLoc())); |
5594 |
0, S, Tok.getEndLoc())); |
| 5595 |
|
5595 |
|
| 5596 |
return ParseStatus::Success; |
5596 |
return ParseStatus::Success; |
| 5597 |
} |
5597 |
} |
| 5598 |
|
5598 |
|
| 5599 |
/// Convert parsed operands to MCInst. Needed here because this instruction |
5599 |
/// Convert parsed operands to MCInst. Needed here because this instruction |
| 5600 |
/// only has two register operands, but multiplication is commutative so |
5600 |
/// only has two register operands, but multiplication is commutative so |
| 5601 |
/// assemblers should accept both "mul rD, rN, rD" and "mul rD, rD, rN". |
5601 |
/// assemblers should accept both "mul rD, rN, rD" and "mul rD, rD, rN". |
| 5602 |
void ARMAsmParser::cvtThumbMultiply(MCInst &Inst, |
5602 |
void ARMAsmParser::cvtThumbMultiply(MCInst &Inst, |
| 5603 |
const OperandVector &Operands) { |
5603 |
const OperandVector &Operands) { |
| 5604 |
((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1); |
5604 |
((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1); |
| 5605 |
((ARMOperand &)*Operands[1]).addCCOutOperands(Inst, 1); |
5605 |
((ARMOperand &)*Operands[1]).addCCOutOperands(Inst, 1); |
| 5606 |
// If we have a three-operand form, make sure to set Rn to be the operand |
5606 |
// If we have a three-operand form, make sure to set Rn to be the operand |
| 5607 |
// that isn't the same as Rd. |
5607 |
// that isn't the same as Rd. |
| 5608 |
unsigned RegOp = 4; |
5608 |
unsigned RegOp = 4; |
| 5609 |
if (Operands.size() == 6 && |
5609 |
if (Operands.size() == 6 && |
| 5610 |
((ARMOperand &)*Operands[4]).getReg() == |
5610 |
((ARMOperand &)*Operands[4]).getReg() == |
| 5611 |
((ARMOperand &)*Operands[3]).getReg()) |
5611 |
((ARMOperand &)*Operands[3]).getReg()) |
| 5612 |
RegOp = 5; |
5612 |
RegOp = 5; |
| 5613 |
((ARMOperand &)*Operands[RegOp]).addRegOperands(Inst, 1); |
5613 |
((ARMOperand &)*Operands[RegOp]).addRegOperands(Inst, 1); |
| 5614 |
Inst.addOperand(Inst.getOperand(0)); |
5614 |
Inst.addOperand(Inst.getOperand(0)); |
| 5615 |
((ARMOperand &)*Operands[2]).addCondCodeOperands(Inst, 2); |
5615 |
((ARMOperand &)*Operands[2]).addCondCodeOperands(Inst, 2); |
| 5616 |
} |
5616 |
} |
| 5617 |
|
5617 |
|
| 5618 |
void ARMAsmParser::cvtThumbBranches(MCInst &Inst, |
5618 |
void ARMAsmParser::cvtThumbBranches(MCInst &Inst, |
| 5619 |
const OperandVector &Operands) { |
5619 |
const OperandVector &Operands) { |
| 5620 |
int CondOp = -1, ImmOp = -1; |
5620 |
int CondOp = -1, ImmOp = -1; |
| 5621 |
switch(Inst.getOpcode()) { |
5621 |
switch(Inst.getOpcode()) { |
| 5622 |
case ARM::tB: |
5622 |
case ARM::tB: |
| 5623 |
case ARM::tBcc: CondOp = 1; ImmOp = 2; break; |
5623 |
case ARM::tBcc: CondOp = 1; ImmOp = 2; break; |
| 5624 |
|
5624 |
|
| 5625 |
case ARM::t2B: |
5625 |
case ARM::t2B: |
| 5626 |
case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break; |
5626 |
case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break; |
| 5627 |
|
5627 |
|
| 5628 |
default: llvm_unreachable("Unexpected instruction in cvtThumbBranches"); |
5628 |
default: llvm_unreachable("Unexpected instruction in cvtThumbBranches"); |
| 5629 |
} |
5629 |
} |
| 5630 |
// first decide whether or not the branch should be conditional |
5630 |
// first decide whether or not the branch should be conditional |
| 5631 |
// by looking at it's location relative to an IT block |
5631 |
// by looking at it's location relative to an IT block |
| 5632 |
if(inITBlock()) { |
5632 |
if(inITBlock()) { |
| 5633 |
// inside an IT block we cannot have any conditional branches. any |
5633 |
// inside an IT block we cannot have any conditional branches. any |
| 5634 |
// such instructions needs to be converted to unconditional form |
5634 |
// such instructions needs to be converted to unconditional form |
| 5635 |
switch(Inst.getOpcode()) { |
5635 |
switch(Inst.getOpcode()) { |
| 5636 |
case ARM::tBcc: Inst.setOpcode(ARM::tB); break; |
5636 |
case ARM::tBcc: Inst.setOpcode(ARM::tB); break; |
| 5637 |
case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break; |
5637 |
case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break; |
| 5638 |
} |
5638 |
} |
| 5639 |
} else { |
5639 |
} else { |
| 5640 |
// outside IT blocks we can only have unconditional branches with AL |
5640 |
// outside IT blocks we can only have unconditional branches with AL |
| 5641 |
// condition code or conditional branches with non-AL condition code |
5641 |
// condition code or conditional branches with non-AL condition code |
| 5642 |
unsigned Cond = static_cast(*Operands[CondOp]).getCondCode(); |
5642 |
unsigned Cond = static_cast(*Operands[CondOp]).getCondCode(); |
| 5643 |
switch(Inst.getOpcode()) { |
5643 |
switch(Inst.getOpcode()) { |
| 5644 |
case ARM::tB: |
5644 |
case ARM::tB: |
| 5645 |
case ARM::tBcc: |
5645 |
case ARM::tBcc: |
| 5646 |
Inst.setOpcode(Cond == ARMCC::AL ? ARM::tB : ARM::tBcc); |
5646 |
Inst.setOpcode(Cond == ARMCC::AL ? ARM::tB : ARM::tBcc); |
| 5647 |
break; |
5647 |
break; |
| 5648 |
case ARM::t2B: |
5648 |
case ARM::t2B: |
| 5649 |
case ARM::t2Bcc: |
5649 |
case ARM::t2Bcc: |
| 5650 |
Inst.setOpcode(Cond == ARMCC::AL ? ARM::t2B : ARM::t2Bcc); |
5650 |
Inst.setOpcode(Cond == ARMCC::AL ? ARM::t2B : ARM::t2Bcc); |
| 5651 |
break; |
5651 |
break; |
| 5652 |
} |
5652 |
} |
| 5653 |
} |
5653 |
} |
| 5654 |
|
5654 |
|
| 5655 |
// now decide on encoding size based on branch target range |
5655 |
// now decide on encoding size based on branch target range |
| 5656 |
switch(Inst.getOpcode()) { |
5656 |
switch(Inst.getOpcode()) { |
| 5657 |
// classify tB as either t2B or t1B based on range of immediate operand |
5657 |
// classify tB as either t2B or t1B based on range of immediate operand |
| 5658 |
case ARM::tB: { |
5658 |
case ARM::tB: { |
| 5659 |
ARMOperand &op = static_cast(*Operands[ImmOp]); |
5659 |
ARMOperand &op = static_cast(*Operands[ImmOp]); |
| 5660 |
if (!op.isSignedOffset<11, 1>() && isThumb() && hasV8MBaseline()) |
5660 |
if (!op.isSignedOffset<11, 1>() && isThumb() && hasV8MBaseline()) |
| 5661 |
Inst.setOpcode(ARM::t2B); |
5661 |
Inst.setOpcode(ARM::t2B); |
| 5662 |
break; |
5662 |
break; |
| 5663 |
} |
5663 |
} |
| 5664 |
// classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand |
5664 |
// classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand |
| 5665 |
case ARM::tBcc: { |
5665 |
case ARM::tBcc: { |
| 5666 |
ARMOperand &op = static_cast(*Operands[ImmOp]); |
5666 |
ARMOperand &op = static_cast(*Operands[ImmOp]); |
| 5667 |
if (!op.isSignedOffset<8, 1>() && isThumb() && hasV8MBaseline()) |
5667 |
if (!op.isSignedOffset<8, 1>() && isThumb() && hasV8MBaseline()) |
| 5668 |
Inst.setOpcode(ARM::t2Bcc); |
5668 |
Inst.setOpcode(ARM::t2Bcc); |
| 5669 |
break; |
5669 |
break; |
| 5670 |
} |
5670 |
} |
| 5671 |
} |
5671 |
} |
| 5672 |
((ARMOperand &)*Operands[ImmOp]).addImmOperands(Inst, 1); |
5672 |
((ARMOperand &)*Operands[ImmOp]).addImmOperands(Inst, 1); |
| 5673 |
((ARMOperand &)*Operands[CondOp]).addCondCodeOperands(Inst, 2); |
5673 |
((ARMOperand &)*Operands[CondOp]).addCondCodeOperands(Inst, 2); |
| 5674 |
} |
5674 |
} |
| 5675 |
|
5675 |
|
| 5676 |
void ARMAsmParser::cvtMVEVMOVQtoDReg( |
5676 |
void ARMAsmParser::cvtMVEVMOVQtoDReg( |
| 5677 |
MCInst &Inst, const OperandVector &Operands) { |
5677 |
MCInst &Inst, const OperandVector &Operands) { |
| 5678 |
|
5678 |
|
| 5679 |
// mnemonic, condition code, Rt, Rt2, Qd, idx, Qd again, idx2 |
5679 |
// mnemonic, condition code, Rt, Rt2, Qd, idx, Qd again, idx2 |
| 5680 |
assert(Operands.size() == 8); |
5680 |
assert(Operands.size() == 8); |
| 5681 |
|
5681 |
|
| 5682 |
((ARMOperand &)*Operands[2]).addRegOperands(Inst, 1); // Rt |
5682 |
((ARMOperand &)*Operands[2]).addRegOperands(Inst, 1); // Rt |
| 5683 |
((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1); // Rt2 |
5683 |
((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1); // Rt2 |
| 5684 |
((ARMOperand &)*Operands[4]).addRegOperands(Inst, 1); // Qd |
5684 |
((ARMOperand &)*Operands[4]).addRegOperands(Inst, 1); // Qd |
| 5685 |
((ARMOperand &)*Operands[5]).addMVEPairVectorIndexOperands(Inst, 1); // idx |
5685 |
((ARMOperand &)*Operands[5]).addMVEPairVectorIndexOperands(Inst, 1); // idx |
| 5686 |
// skip second copy of Qd in Operands[6] |
5686 |
// skip second copy of Qd in Operands[6] |
| 5687 |
((ARMOperand &)*Operands[7]).addMVEPairVectorIndexOperands(Inst, 1); // idx2 |
5687 |
((ARMOperand &)*Operands[7]).addMVEPairVectorIndexOperands(Inst, 1); // idx2 |
| 5688 |
((ARMOperand &)*Operands[1]).addCondCodeOperands(Inst, 2); // condition code |
5688 |
((ARMOperand &)*Operands[1]).addCondCodeOperands(Inst, 2); // condition code |
| 5689 |
} |
5689 |
} |
| 5690 |
|
5690 |
|
| 5691 |
/// Parse an ARM memory expression, return false if successful else return true |
5691 |
/// Parse an ARM memory expression, return false if successful else return true |
| 5692 |
/// or an error. The first token must be a '[' when called. |
5692 |
/// or an error. The first token must be a '[' when called. |
| 5693 |
bool ARMAsmParser::parseMemory(OperandVector &Operands) { |
5693 |
bool ARMAsmParser::parseMemory(OperandVector &Operands) { |
| 5694 |
MCAsmParser &Parser = getParser(); |
5694 |
MCAsmParser &Parser = getParser(); |
| 5695 |
SMLoc S, E; |
5695 |
SMLoc S, E; |
| 5696 |
if (Parser.getTok().isNot(AsmToken::LBrac)) |
5696 |
if (Parser.getTok().isNot(AsmToken::LBrac)) |
| 5697 |
return TokError("Token is not a Left Bracket"); |
5697 |
return TokError("Token is not a Left Bracket"); |
| 5698 |
S = Parser.getTok().getLoc(); |
5698 |
S = Parser.getTok().getLoc(); |
| 5699 |
Parser.Lex(); // Eat left bracket token. |
5699 |
Parser.Lex(); // Eat left bracket token. |
| 5700 |
|
5700 |
|
| 5701 |
const AsmToken &BaseRegTok = Parser.getTok(); |
5701 |
const AsmToken &BaseRegTok = Parser.getTok(); |
| 5702 |
int BaseRegNum = tryParseRegister(); |
5702 |
int BaseRegNum = tryParseRegister(); |
| 5703 |
if (BaseRegNum == -1) |
5703 |
if (BaseRegNum == -1) |
| 5704 |
return Error(BaseRegTok.getLoc(), "register expected"); |
5704 |
return Error(BaseRegTok.getLoc(), "register expected"); |
| 5705 |
|
5705 |
|
| 5706 |
// The next token must either be a comma, a colon or a closing bracket. |
5706 |
// The next token must either be a comma, a colon or a closing bracket. |
| 5707 |
const AsmToken &Tok = Parser.getTok(); |
5707 |
const AsmToken &Tok = Parser.getTok(); |
| 5708 |
if (!Tok.is(AsmToken::Colon) && !Tok.is(AsmToken::Comma) && |
5708 |
if (!Tok.is(AsmToken::Colon) && !Tok.is(AsmToken::Comma) && |
| 5709 |
!Tok.is(AsmToken::RBrac)) |
5709 |
!Tok.is(AsmToken::RBrac)) |
| 5710 |
return Error(Tok.getLoc(), "malformed memory operand"); |
5710 |
return Error(Tok.getLoc(), "malformed memory operand"); |
| 5711 |
|
5711 |
|
| 5712 |
if (Tok.is(AsmToken::RBrac)) { |
5712 |
if (Tok.is(AsmToken::RBrac)) { |
| 5713 |
E = Tok.getEndLoc(); |
5713 |
E = Tok.getEndLoc(); |
| 5714 |
Parser.Lex(); // Eat right bracket token. |
5714 |
Parser.Lex(); // Eat right bracket token. |
| 5715 |
|
5715 |
|
| 5716 |
Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0, |
5716 |
Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0, |
| 5717 |
ARM_AM::no_shift, 0, 0, false, |
5717 |
ARM_AM::no_shift, 0, 0, false, |
| 5718 |
S, E)); |
5718 |
S, E)); |
| 5719 |
|
5719 |
|
| 5720 |
// If there's a pre-indexing writeback marker, '!', just add it as a token |
5720 |
// If there's a pre-indexing writeback marker, '!', just add it as a token |
| 5721 |
// operand. It's rather odd, but syntactically valid. |
5721 |
// operand. It's rather odd, but syntactically valid. |
| 5722 |
if (Parser.getTok().is(AsmToken::Exclaim)) { |
5722 |
if (Parser.getTok().is(AsmToken::Exclaim)) { |
| 5723 |
Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); |
5723 |
Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); |
| 5724 |
Parser.Lex(); // Eat the '!'. |
5724 |
Parser.Lex(); // Eat the '!'. |
| 5725 |
} |
5725 |
} |
| 5726 |
|
5726 |
|
| 5727 |
return false; |
5727 |
return false; |
| 5728 |
} |
5728 |
} |
| 5729 |
|
5729 |
|
| 5730 |
assert((Tok.is(AsmToken::Colon) || Tok.is(AsmToken::Comma)) && |
5730 |
assert((Tok.is(AsmToken::Colon) || Tok.is(AsmToken::Comma)) && |
| 5731 |
"Lost colon or comma in memory operand?!"); |
5731 |
"Lost colon or comma in memory operand?!"); |
| 5732 |
if (Tok.is(AsmToken::Comma)) { |
5732 |
if (Tok.is(AsmToken::Comma)) { |
| 5733 |
Parser.Lex(); // Eat the comma. |
5733 |
Parser.Lex(); // Eat the comma. |
| 5734 |
} |
5734 |
} |
| 5735 |
|
5735 |
|
| 5736 |
// If we have a ':', it's an alignment specifier. |
5736 |
// If we have a ':', it's an alignment specifier. |
| 5737 |
if (Parser.getTok().is(AsmToken::Colon)) { |
5737 |
if (Parser.getTok().is(AsmToken::Colon)) { |
| 5738 |
Parser.Lex(); // Eat the ':'. |
5738 |
Parser.Lex(); // Eat the ':'. |
| 5739 |
E = Parser.getTok().getLoc(); |
5739 |
E = Parser.getTok().getLoc(); |
| 5740 |
SMLoc AlignmentLoc = Tok.getLoc(); |
5740 |
SMLoc AlignmentLoc = Tok.getLoc(); |
| 5741 |
|
5741 |
|
| 5742 |
const MCExpr *Expr; |
5742 |
const MCExpr *Expr; |
| 5743 |
if (getParser().parseExpression(Expr)) |
5743 |
if (getParser().parseExpression(Expr)) |
| 5744 |
return true; |
5744 |
return true; |
| 5745 |
|
5745 |
|
| 5746 |
// The expression has to be a constant. Memory references with relocations |
5746 |
// The expression has to be a constant. Memory references with relocations |
| 5747 |
// don't come through here, as they use the |
5747 |
// don't come through here, as they use the |
| 5748 |
// instructions. |
5748 |
// instructions. |
| 5749 |
const MCConstantExpr *CE = dyn_cast(Expr); |
5749 |
const MCConstantExpr *CE = dyn_cast(Expr); |
| 5750 |
if (!CE) |
5750 |
if (!CE) |
| 5751 |
return Error (E, "constant expression expected"); |
5751 |
return Error (E, "constant expression expected"); |
| 5752 |
|
5752 |
|
| 5753 |
unsigned Align = 0; |
5753 |
unsigned Align = 0; |
| 5754 |
switch (CE->getValue()) { |
5754 |
switch (CE->getValue()) { |
| 5755 |
default: |
5755 |
default: |
| 5756 |
return Error(E, |
5756 |
return Error(E, |
| 5757 |
"alignment specifier must be 16, 32, 64, 128, or 256 bits"); |
5757 |
"alignment specifier must be 16, 32, 64, 128, or 256 bits"); |
| 5758 |
case 16: Align = 2; break; |
5758 |
case 16: Align = 2; break; |
| 5759 |
case 32: Align = 4; break; |
5759 |
case 32: Align = 4; break; |
| 5760 |
case 64: Align = 8; break; |
5760 |
case 64: Align = 8; break; |
| 5761 |
case 128: Align = 16; break; |
5761 |
case 128: Align = 16; break; |
| 5762 |
case 256: Align = 32; break; |
5762 |
case 256: Align = 32; break; |
| 5763 |
} |
5763 |
} |
| 5764 |
|
5764 |
|
| 5765 |
// Now we should have the closing ']' |
5765 |
// Now we should have the closing ']' |
| 5766 |
if (Parser.getTok().isNot(AsmToken::RBrac)) |
5766 |
if (Parser.getTok().isNot(AsmToken::RBrac)) |
| 5767 |
return Error(Parser.getTok().getLoc(), "']' expected"); |
5767 |
return Error(Parser.getTok().getLoc(), "']' expected"); |
| 5768 |
E = Parser.getTok().getEndLoc(); |
5768 |
E = Parser.getTok().getEndLoc(); |
| 5769 |
Parser.Lex(); // Eat right bracket token. |
5769 |
Parser.Lex(); // Eat right bracket token. |
| 5770 |
|
5770 |
|
| 5771 |
// Don't worry about range checking the value here. That's handled by |
5771 |
// Don't worry about range checking the value here. That's handled by |
| 5772 |
// the is*() predicates. |
5772 |
// the is*() predicates. |
| 5773 |
Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0, |
5773 |
Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0, |
| 5774 |
ARM_AM::no_shift, 0, Align, |
5774 |
ARM_AM::no_shift, 0, Align, |
| 5775 |
false, S, E, AlignmentLoc)); |
5775 |
false, S, E, AlignmentLoc)); |
| 5776 |
|
5776 |
|
| 5777 |
// If there's a pre-indexing writeback marker, '!', just add it as a token |
5777 |
// If there's a pre-indexing writeback marker, '!', just add it as a token |
| 5778 |
// operand. |
5778 |
// operand. |
| 5779 |
if (Parser.getTok().is(AsmToken::Exclaim)) { |
5779 |
if (Parser.getTok().is(AsmToken::Exclaim)) { |
| 5780 |
Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); |
5780 |
Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); |
| 5781 |
Parser.Lex(); // Eat the '!'. |
5781 |
Parser.Lex(); // Eat the '!'. |
| 5782 |
} |
5782 |
} |
| 5783 |
|
5783 |
|
| 5784 |
return false; |
5784 |
return false; |
| 5785 |
} |
5785 |
} |
| 5786 |
|
5786 |
|
| 5787 |
// If we have a '#' or '$', it's an immediate offset, else assume it's a |
5787 |
// If we have a '#' or '$', it's an immediate offset, else assume it's a |
| 5788 |
// register offset. Be friendly and also accept a plain integer or expression |
5788 |
// register offset. Be friendly and also accept a plain integer or expression |
| 5789 |
// (without a leading hash) for gas compatibility. |
5789 |
// (without a leading hash) for gas compatibility. |
| 5790 |
if (Parser.getTok().is(AsmToken::Hash) || |
5790 |
if (Parser.getTok().is(AsmToken::Hash) || |
| 5791 |
Parser.getTok().is(AsmToken::Dollar) || |
5791 |
Parser.getTok().is(AsmToken::Dollar) || |
| 5792 |
Parser.getTok().is(AsmToken::LParen) || |
5792 |
Parser.getTok().is(AsmToken::LParen) || |
| 5793 |
Parser.getTok().is(AsmToken::Integer)) { |
5793 |
Parser.getTok().is(AsmToken::Integer)) { |
| 5794 |
if (Parser.getTok().is(AsmToken::Hash) || |
5794 |
if (Parser.getTok().is(AsmToken::Hash) || |
| 5795 |
Parser.getTok().is(AsmToken::Dollar)) |
5795 |
Parser.getTok().is(AsmToken::Dollar)) |
| 5796 |
Parser.Lex(); // Eat '#' or '$' |
5796 |
Parser.Lex(); // Eat '#' or '$' |
| 5797 |
E = Parser.getTok().getLoc(); |
5797 |
E = Parser.getTok().getLoc(); |
| 5798 |
|
5798 |
|
| 5799 |
bool isNegative = getParser().getTok().is(AsmToken::Minus); |
5799 |
bool isNegative = getParser().getTok().is(AsmToken::Minus); |
| 5800 |
const MCExpr *Offset, *AdjustedOffset; |
5800 |
const MCExpr *Offset, *AdjustedOffset; |
| 5801 |
if (getParser().parseExpression(Offset)) |
5801 |
if (getParser().parseExpression(Offset)) |
| 5802 |
return true; |
5802 |
return true; |
| 5803 |
|
5803 |
|
| 5804 |
if (const auto *CE = dyn_cast(Offset)) { |
5804 |
if (const auto *CE = dyn_cast(Offset)) { |
| 5805 |
// If the constant was #-0, represent it as |
5805 |
// If the constant was #-0, represent it as |
| 5806 |
// std::numeric_limits::min(). |
5806 |
// std::numeric_limits::min(). |
| 5807 |
int32_t Val = CE->getValue(); |
5807 |
int32_t Val = CE->getValue(); |
| 5808 |
if (isNegative && Val == 0) |
5808 |
if (isNegative && Val == 0) |
| 5809 |
CE = MCConstantExpr::create(std::numeric_limits::min(), |
5809 |
CE = MCConstantExpr::create(std::numeric_limits::min(), |
| 5810 |
getContext()); |
5810 |
getContext()); |
| 5811 |
// Don't worry about range checking the value here. That's handled by |
5811 |
// Don't worry about range checking the value here. That's handled by |
| 5812 |
// the is*() predicates. |
5812 |
// the is*() predicates. |
| 5813 |
AdjustedOffset = CE; |
5813 |
AdjustedOffset = CE; |
| 5814 |
} else |
5814 |
} else |
| 5815 |
AdjustedOffset = Offset; |
5815 |
AdjustedOffset = Offset; |
| 5816 |
Operands.push_back(ARMOperand::CreateMem( |
5816 |
Operands.push_back(ARMOperand::CreateMem( |
| 5817 |
BaseRegNum, AdjustedOffset, 0, ARM_AM::no_shift, 0, 0, false, S, E)); |
5817 |
BaseRegNum, AdjustedOffset, 0, ARM_AM::no_shift, 0, 0, false, S, E)); |
| 5818 |
|
5818 |
|
| 5819 |
// Now we should have the closing ']' |
5819 |
// Now we should have the closing ']' |
| 5820 |
if (Parser.getTok().isNot(AsmToken::RBrac)) |
5820 |
if (Parser.getTok().isNot(AsmToken::RBrac)) |
| 5821 |
return Error(Parser.getTok().getLoc(), "']' expected"); |
5821 |
return Error(Parser.getTok().getLoc(), "']' expected"); |
| 5822 |
E = Parser.getTok().getEndLoc(); |
5822 |
E = Parser.getTok().getEndLoc(); |
| 5823 |
Parser.Lex(); // Eat right bracket token. |
5823 |
Parser.Lex(); // Eat right bracket token. |
| 5824 |
|
5824 |
|
| 5825 |
// If there's a pre-indexing writeback marker, '!', just add it as a token |
5825 |
// If there's a pre-indexing writeback marker, '!', just add it as a token |
| 5826 |
// operand. |
5826 |
// operand. |
| 5827 |
if (Parser.getTok().is(AsmToken::Exclaim)) { |
5827 |
if (Parser.getTok().is(AsmToken::Exclaim)) { |
| 5828 |
Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); |
5828 |
Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); |
| 5829 |
Parser.Lex(); // Eat the '!'. |
5829 |
Parser.Lex(); // Eat the '!'. |
| 5830 |
} |
5830 |
} |
| 5831 |
|
5831 |
|
| 5832 |
return false; |
5832 |
return false; |
| 5833 |
} |
5833 |
} |
| 5834 |
|
5834 |
|
| 5835 |
// The register offset is optionally preceded by a '+' or '-' |
5835 |
// The register offset is optionally preceded by a '+' or '-' |
| 5836 |
bool isNegative = false; |
5836 |
bool isNegative = false; |
| 5837 |
if (Parser.getTok().is(AsmToken::Minus)) { |
5837 |
if (Parser.getTok().is(AsmToken::Minus)) { |
| 5838 |
isNegative = true; |
5838 |
isNegative = true; |
| 5839 |
Parser.Lex(); // Eat the '-'. |
5839 |
Parser.Lex(); // Eat the '-'. |
| 5840 |
} else if (Parser.getTok().is(AsmToken::Plus)) { |
5840 |
} else if (Parser.getTok().is(AsmToken::Plus)) { |
| 5841 |
// Nothing to do. |
5841 |
// Nothing to do. |
| 5842 |
Parser.Lex(); // Eat the '+'. |
5842 |
Parser.Lex(); // Eat the '+'. |
| 5843 |
} |
5843 |
} |
| 5844 |
|
5844 |
|
| 5845 |
E = Parser.getTok().getLoc(); |
5845 |
E = Parser.getTok().getLoc(); |
| 5846 |
int OffsetRegNum = tryParseRegister(); |
5846 |
int OffsetRegNum = tryParseRegister(); |
| 5847 |
if (OffsetRegNum == -1) |
5847 |
if (OffsetRegNum == -1) |
| 5848 |
return Error(E, "register expected"); |
5848 |
return Error(E, "register expected"); |
| 5849 |
|
5849 |
|
| 5850 |
// If there's a shift operator, handle it. |
5850 |
// If there's a shift operator, handle it. |
| 5851 |
ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift; |
5851 |
ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift; |
| 5852 |
unsigned ShiftImm = 0; |
5852 |
unsigned ShiftImm = 0; |
| 5853 |
if (Parser.getTok().is(AsmToken::Comma)) { |
5853 |
if (Parser.getTok().is(AsmToken::Comma)) { |
| 5854 |
Parser.Lex(); // Eat the ','. |
5854 |
Parser.Lex(); // Eat the ','. |
| 5855 |
if (parseMemRegOffsetShift(ShiftType, ShiftImm)) |
5855 |
if (parseMemRegOffsetShift(ShiftType, ShiftImm)) |
| 5856 |
return true; |
5856 |
return true; |
| 5857 |
} |
5857 |
} |
| 5858 |
|
5858 |
|
| 5859 |
// Now we should have the closing ']' |
5859 |
// Now we should have the closing ']' |
| 5860 |
if (Parser.getTok().isNot(AsmToken::RBrac)) |
5860 |
if (Parser.getTok().isNot(AsmToken::RBrac)) |
| 5861 |
return Error(Parser.getTok().getLoc(), "']' expected"); |
5861 |
return Error(Parser.getTok().getLoc(), "']' expected"); |
| 5862 |
E = Parser.getTok().getEndLoc(); |
5862 |
E = Parser.getTok().getEndLoc(); |
| 5863 |
Parser.Lex(); // Eat right bracket token. |
5863 |
Parser.Lex(); // Eat right bracket token. |
| 5864 |
|
5864 |
|
| 5865 |
Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, OffsetRegNum, |
5865 |
Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, OffsetRegNum, |
| 5866 |
ShiftType, ShiftImm, 0, isNegative, |
5866 |
ShiftType, ShiftImm, 0, isNegative, |
| 5867 |
S, E)); |
5867 |
S, E)); |
| 5868 |
|
5868 |
|
| 5869 |
// If there's a pre-indexing writeback marker, '!', just add it as a token |
5869 |
// If there's a pre-indexing writeback marker, '!', just add it as a token |
| 5870 |
// operand. |
5870 |
// operand. |
| 5871 |
if (Parser.getTok().is(AsmToken::Exclaim)) { |
5871 |
if (Parser.getTok().is(AsmToken::Exclaim)) { |
| 5872 |
Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); |
5872 |
Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); |
| 5873 |
Parser.Lex(); // Eat the '!'. |
5873 |
Parser.Lex(); // Eat the '!'. |
| 5874 |
} |
5874 |
} |
| 5875 |
|
5875 |
|
| 5876 |
return false; |
5876 |
return false; |
| 5877 |
} |
5877 |
} |
| 5878 |
|
5878 |
|
| 5879 |
/// parseMemRegOffsetShift - one of these two: |
5879 |
/// parseMemRegOffsetShift - one of these two: |
| 5880 |
/// ( lsl | lsr | asr | ror ) , # shift_amount |
5880 |
/// ( lsl | lsr | asr | ror ) , # shift_amount |
| 5881 |
/// rrx |
5881 |
/// rrx |
| 5882 |
/// return true if it parses a shift otherwise it returns false. |
5882 |
/// return true if it parses a shift otherwise it returns false. |
| 5883 |
bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St, |
5883 |
bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St, |
| 5884 |
unsigned &Amount) { |
5884 |
unsigned &Amount) { |
| 5885 |
MCAsmParser &Parser = getParser(); |
5885 |
MCAsmParser &Parser = getParser(); |
| 5886 |
SMLoc Loc = Parser.getTok().getLoc(); |
5886 |
SMLoc Loc = Parser.getTok().getLoc(); |
| 5887 |
const AsmToken &Tok = Parser.getTok(); |
5887 |
const AsmToken &Tok = Parser.getTok(); |
| 5888 |
if (Tok.isNot(AsmToken::Identifier)) |
5888 |
if (Tok.isNot(AsmToken::Identifier)) |
| 5889 |
return Error(Loc, "illegal shift operator"); |
5889 |
return Error(Loc, "illegal shift operator"); |
| 5890 |
StringRef ShiftName = Tok.getString(); |
5890 |
StringRef ShiftName = Tok.getString(); |
| 5891 |
if (ShiftName == "lsl" || ShiftName == "LSL" || |
5891 |
if (ShiftName == "lsl" || ShiftName == "LSL" || |
| 5892 |
ShiftName == "asl" || ShiftName == "ASL") |
5892 |
ShiftName == "asl" || ShiftName == "ASL") |
| 5893 |
St = ARM_AM::lsl; |
5893 |
St = ARM_AM::lsl; |
| 5894 |
else if (ShiftName == "lsr" || ShiftName == "LSR") |
5894 |
else if (ShiftName == "lsr" || ShiftName == "LSR") |
| 5895 |
St = ARM_AM::lsr; |
5895 |
St = ARM_AM::lsr; |
| 5896 |
else if (ShiftName == "asr" || ShiftName == "ASR") |
5896 |
else if (ShiftName == "asr" || ShiftName == "ASR") |
| 5897 |
St = ARM_AM::asr; |
5897 |
St = ARM_AM::asr; |
| 5898 |
else if (ShiftName == "ror" || ShiftName == "ROR") |
5898 |
else if (ShiftName == "ror" || ShiftName == "ROR") |
| 5899 |
St = ARM_AM::ror; |
5899 |
St = ARM_AM::ror; |
| 5900 |
else if (ShiftName == "rrx" || ShiftName == "RRX") |
5900 |
else if (ShiftName == "rrx" || ShiftName == "RRX") |
| 5901 |
St = ARM_AM::rrx; |
5901 |
St = ARM_AM::rrx; |
| 5902 |
else if (ShiftName == "uxtw" || ShiftName == "UXTW") |
5902 |
else if (ShiftName == "uxtw" || ShiftName == "UXTW") |
| 5903 |
St = ARM_AM::uxtw; |
5903 |
St = ARM_AM::uxtw; |
| 5904 |
else |
5904 |
else |
| 5905 |
return Error(Loc, "illegal shift operator"); |
5905 |
return Error(Loc, "illegal shift operator"); |
| 5906 |
Parser.Lex(); // Eat shift type token. |
5906 |
Parser.Lex(); // Eat shift type token. |
| 5907 |
|
5907 |
|
| 5908 |
// rrx stands alone. |
5908 |
// rrx stands alone. |
| 5909 |
Amount = 0; |
5909 |
Amount = 0; |
| 5910 |
if (St != ARM_AM::rrx) { |
5910 |
if (St != ARM_AM::rrx) { |
| 5911 |
Loc = Parser.getTok().getLoc(); |
5911 |
Loc = Parser.getTok().getLoc(); |
| 5912 |
// A '#' and a shift amount. |
5912 |
// A '#' and a shift amount. |
| 5913 |
const AsmToken &HashTok = Parser.getTok(); |
5913 |
const AsmToken &HashTok = Parser.getTok(); |
| 5914 |
if (HashTok.isNot(AsmToken::Hash) && |
5914 |
if (HashTok.isNot(AsmToken::Hash) && |
| 5915 |
HashTok.isNot(AsmToken::Dollar)) |
5915 |
HashTok.isNot(AsmToken::Dollar)) |
| 5916 |
return Error(HashTok.getLoc(), "'#' expected"); |
5916 |
return Error(HashTok.getLoc(), "'#' expected"); |
| 5917 |
Parser.Lex(); // Eat hash token. |
5917 |
Parser.Lex(); // Eat hash token. |
| 5918 |
|
5918 |
|
| 5919 |
const MCExpr *Expr; |
5919 |
const MCExpr *Expr; |
| 5920 |
if (getParser().parseExpression(Expr)) |
5920 |
if (getParser().parseExpression(Expr)) |
| 5921 |
return true; |
5921 |
return true; |
| 5922 |
// Range check the immediate. |
5922 |
// Range check the immediate. |
| 5923 |
// lsl, ror: 0 <= imm <= 31 |
5923 |
// lsl, ror: 0 <= imm <= 31 |
| 5924 |
// lsr, asr: 0 <= imm <= 32 |
5924 |
// lsr, asr: 0 <= imm <= 32 |
| 5925 |
const MCConstantExpr *CE = dyn_cast(Expr); |
5925 |
const MCConstantExpr *CE = dyn_cast(Expr); |
| 5926 |
if (!CE) |
5926 |
if (!CE) |
| 5927 |
return Error(Loc, "shift amount must be an immediate"); |
5927 |
return Error(Loc, "shift amount must be an immediate"); |
| 5928 |
int64_t Imm = CE->getValue(); |
5928 |
int64_t Imm = CE->getValue(); |
| 5929 |
if (Imm < 0 || |
5929 |
if (Imm < 0 || |
| 5930 |
((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) || |
5930 |
((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) || |
| 5931 |
((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32)) |
5931 |
((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32)) |
| 5932 |
return Error(Loc, "immediate shift value out of range"); |
5932 |
return Error(Loc, "immediate shift value out of range"); |
| 5933 |
// If #0, turn it into a no_shift. |
5933 |
// If #0, turn it into a no_shift. |
| 5934 |
if (Imm == 0) |
5934 |
if (Imm == 0) |
| 5935 |
St = ARM_AM::lsl; |
5935 |
St = ARM_AM::lsl; |
| 5936 |
// For consistency, treat lsr #32 and asr #32 as having immediate value 0. |
5936 |
// For consistency, treat lsr #32 and asr #32 as having immediate value 0. |
| 5937 |
if (Imm == 32) |
5937 |
if (Imm == 32) |
| 5938 |
Imm = 0; |
5938 |
Imm = 0; |
| 5939 |
Amount = Imm; |
5939 |
Amount = Imm; |
| 5940 |
} |
5940 |
} |
| 5941 |
|
5941 |
|
| 5942 |
return false; |
5942 |
return false; |
| 5943 |
} |
5943 |
} |
| 5944 |
|
5944 |
|
| 5945 |
/// parseFPImm - A floating point immediate expression operand. |
5945 |
/// parseFPImm - A floating point immediate expression operand. |
| 5946 |
ParseStatus ARMAsmParser::parseFPImm(OperandVector &Operands) { |
5946 |
ParseStatus ARMAsmParser::parseFPImm(OperandVector &Operands) { |
| 5947 |
MCAsmParser &Parser = getParser(); |
5947 |
MCAsmParser &Parser = getParser(); |
| 5948 |
// Anything that can accept a floating point constant as an operand |
5948 |
// Anything that can accept a floating point constant as an operand |
| 5949 |
// needs to go through here, as the regular parseExpression is |
5949 |
// needs to go through here, as the regular parseExpression is |
| 5950 |
// integer only. |
5950 |
// integer only. |
| 5951 |
// |
5951 |
// |
| 5952 |
// This routine still creates a generic Immediate operand, containing |
5952 |
// This routine still creates a generic Immediate operand, containing |
| 5953 |
// a bitcast of the 64-bit floating point value. The various operands |
5953 |
// a bitcast of the 64-bit floating point value. The various operands |
| 5954 |
// that accept floats can check whether the value is valid for them |
5954 |
// that accept floats can check whether the value is valid for them |
| 5955 |
// via the standard is*() predicates. |
5955 |
// via the standard is*() predicates. |
| 5956 |
|
5956 |
|
| 5957 |
SMLoc S = Parser.getTok().getLoc(); |
5957 |
SMLoc S = Parser.getTok().getLoc(); |
| 5958 |
|
5958 |
|
| 5959 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
5959 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
| 5960 |
Parser.getTok().isNot(AsmToken::Dollar)) |
5960 |
Parser.getTok().isNot(AsmToken::Dollar)) |
| 5961 |
return ParseStatus::NoMatch; |
5961 |
return ParseStatus::NoMatch; |
| 5962 |
|
5962 |
|
| 5963 |
// Disambiguate the VMOV forms that can accept an FP immediate. |
5963 |
// Disambiguate the VMOV forms that can accept an FP immediate. |
| 5964 |
// vmov.f32 , #imm |
5964 |
// vmov.f32 , #imm |
| 5965 |
// vmov.f64 , #imm |
5965 |
// vmov.f64 , #imm |
| 5966 |
// vmov.f32 , #imm @ vector f32x2 |
5966 |
// vmov.f32 , #imm @ vector f32x2 |
| 5967 |
// vmov.f32 , #imm @ vector f32x4 |
5967 |
// vmov.f32 , #imm @ vector f32x4 |
| 5968 |
// |
5968 |
// |
| 5969 |
// There are also the NEON VMOV instructions which expect an |
5969 |
// There are also the NEON VMOV instructions which expect an |
| 5970 |
// integer constant. Make sure we don't try to parse an FPImm |
5970 |
// integer constant. Make sure we don't try to parse an FPImm |
| 5971 |
// for these: |
5971 |
// for these: |
| 5972 |
// vmov.i{8|16|32|64} , #imm |
5972 |
// vmov.i{8|16|32|64} , #imm |
| 5973 |
ARMOperand &TyOp = static_cast(*Operands[2]); |
5973 |
ARMOperand &TyOp = static_cast(*Operands[2]); |
| 5974 |
bool isVmovf = TyOp.isToken() && |
5974 |
bool isVmovf = TyOp.isToken() && |
| 5975 |
(TyOp.getToken() == ".f32" || TyOp.getToken() == ".f64" || |
5975 |
(TyOp.getToken() == ".f32" || TyOp.getToken() == ".f64" || |
| 5976 |
TyOp.getToken() == ".f16"); |
5976 |
TyOp.getToken() == ".f16"); |
| 5977 |
ARMOperand &Mnemonic = static_cast(*Operands[0]); |
5977 |
ARMOperand &Mnemonic = static_cast(*Operands[0]); |
| 5978 |
bool isFconst = Mnemonic.isToken() && (Mnemonic.getToken() == "fconstd" || |
5978 |
bool isFconst = Mnemonic.isToken() && (Mnemonic.getToken() == "fconstd" || |
| 5979 |
Mnemonic.getToken() == "fconsts"); |
5979 |
Mnemonic.getToken() == "fconsts"); |
| 5980 |
if (!(isVmovf || isFconst)) |
5980 |
if (!(isVmovf || isFconst)) |
| 5981 |
return ParseStatus::NoMatch; |
5981 |
return ParseStatus::NoMatch; |
| 5982 |
|
5982 |
|
| 5983 |
Parser.Lex(); // Eat '#' or '$'. |
5983 |
Parser.Lex(); // Eat '#' or '$'. |
| 5984 |
|
5984 |
|
| 5985 |
// Handle negation, as that still comes through as a separate token. |
5985 |
// Handle negation, as that still comes through as a separate token. |
| 5986 |
bool isNegative = false; |
5986 |
bool isNegative = false; |
| 5987 |
if (Parser.getTok().is(AsmToken::Minus)) { |
5987 |
if (Parser.getTok().is(AsmToken::Minus)) { |
| 5988 |
isNegative = true; |
5988 |
isNegative = true; |
| 5989 |
Parser.Lex(); |
5989 |
Parser.Lex(); |
| 5990 |
} |
5990 |
} |
| 5991 |
const AsmToken &Tok = Parser.getTok(); |
5991 |
const AsmToken &Tok = Parser.getTok(); |
| 5992 |
SMLoc Loc = Tok.getLoc(); |
5992 |
SMLoc Loc = Tok.getLoc(); |
| 5993 |
if (Tok.is(AsmToken::Real) && isVmovf) { |
5993 |
if (Tok.is(AsmToken::Real) && isVmovf) { |
| 5994 |
APFloat RealVal(APFloat::IEEEsingle(), Tok.getString()); |
5994 |
APFloat RealVal(APFloat::IEEEsingle(), Tok.getString()); |
| 5995 |
uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); |
5995 |
uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); |
| 5996 |
// If we had a '-' in front, toggle the sign bit. |
5996 |
// If we had a '-' in front, toggle the sign bit. |
| 5997 |
IntVal ^= (uint64_t)isNegative << 31; |
5997 |
IntVal ^= (uint64_t)isNegative << 31; |
| 5998 |
Parser.Lex(); // Eat the token. |
5998 |
Parser.Lex(); // Eat the token. |
| 5999 |
Operands.push_back(ARMOperand::CreateImm( |
5999 |
Operands.push_back(ARMOperand::CreateImm( |
| 6000 |
MCConstantExpr::create(IntVal, getContext()), |
6000 |
MCConstantExpr::create(IntVal, getContext()), |
| 6001 |
S, Parser.getTok().getLoc())); |
6001 |
S, Parser.getTok().getLoc())); |
| 6002 |
return ParseStatus::Success; |
6002 |
return ParseStatus::Success; |
| 6003 |
} |
6003 |
} |
| 6004 |
// Also handle plain integers. Instructions which allow floating point |
6004 |
// Also handle plain integers. Instructions which allow floating point |
| 6005 |
// immediates also allow a raw encoded 8-bit value. |
6005 |
// immediates also allow a raw encoded 8-bit value. |
| 6006 |
if (Tok.is(AsmToken::Integer) && isFconst) { |
6006 |
if (Tok.is(AsmToken::Integer) && isFconst) { |
| 6007 |
int64_t Val = Tok.getIntVal(); |
6007 |
int64_t Val = Tok.getIntVal(); |
| 6008 |
Parser.Lex(); // Eat the token. |
6008 |
Parser.Lex(); // Eat the token. |
| 6009 |
if (Val > 255 || Val < 0) |
6009 |
if (Val > 255 || Val < 0) |
| 6010 |
return Error(Loc, "encoded floating point value out of range"); |
6010 |
return Error(Loc, "encoded floating point value out of range"); |
| 6011 |
float RealVal = ARM_AM::getFPImmFloat(Val); |
6011 |
float RealVal = ARM_AM::getFPImmFloat(Val); |
| 6012 |
Val = APFloat(RealVal).bitcastToAPInt().getZExtValue(); |
6012 |
Val = APFloat(RealVal).bitcastToAPInt().getZExtValue(); |
| 6013 |
|
6013 |
|
| 6014 |
Operands.push_back(ARMOperand::CreateImm( |
6014 |
Operands.push_back(ARMOperand::CreateImm( |
| 6015 |
MCConstantExpr::create(Val, getContext()), S, |
6015 |
MCConstantExpr::create(Val, getContext()), S, |
| 6016 |
Parser.getTok().getLoc())); |
6016 |
Parser.getTok().getLoc())); |
| 6017 |
return ParseStatus::Success; |
6017 |
return ParseStatus::Success; |
| 6018 |
} |
6018 |
} |
| 6019 |
|
6019 |
|
| 6020 |
return Error(Loc, "invalid floating point immediate"); |
6020 |
return Error(Loc, "invalid floating point immediate"); |
| 6021 |
} |
6021 |
} |
| 6022 |
|
6022 |
|
| 6023 |
/// Parse a arm instruction operand. For now this parses the operand regardless |
6023 |
/// Parse a arm instruction operand. For now this parses the operand regardless |
| 6024 |
/// of the mnemonic. |
6024 |
/// of the mnemonic. |
| 6025 |
bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { |
6025 |
bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { |
| 6026 |
MCAsmParser &Parser = getParser(); |
6026 |
MCAsmParser &Parser = getParser(); |
| 6027 |
SMLoc S, E; |
6027 |
SMLoc S, E; |
| 6028 |
|
6028 |
|
| 6029 |
// Check if the current operand has a custom associated parser, if so, try to |
6029 |
// Check if the current operand has a custom associated parser, if so, try to |
| 6030 |
// custom parse the operand, or fallback to the general approach. |
6030 |
// custom parse the operand, or fallback to the general approach. |
| 6031 |
ParseStatus ResTy = MatchOperandParserImpl(Operands, Mnemonic); |
6031 |
ParseStatus ResTy = MatchOperandParserImpl(Operands, Mnemonic); |
| 6032 |
if (ResTy.isSuccess()) |
6032 |
if (ResTy.isSuccess()) |
| 6033 |
return false; |
6033 |
return false; |
| 6034 |
// If there wasn't a custom match, try the generic matcher below. Otherwise, |
6034 |
// If there wasn't a custom match, try the generic matcher below. Otherwise, |
| 6035 |
// there was a match, but an error occurred, in which case, just return that |
6035 |
// there was a match, but an error occurred, in which case, just return that |
| 6036 |
// the operand parsing failed. |
6036 |
// the operand parsing failed. |
| 6037 |
if (ResTy.isFailure()) |
6037 |
if (ResTy.isFailure()) |
| 6038 |
return true; |
6038 |
return true; |
| 6039 |
|
6039 |
|
| 6040 |
switch (getLexer().getKind()) { |
6040 |
switch (getLexer().getKind()) { |
| 6041 |
default: |
6041 |
default: |
| 6042 |
Error(Parser.getTok().getLoc(), "unexpected token in operand"); |
6042 |
Error(Parser.getTok().getLoc(), "unexpected token in operand"); |
| 6043 |
return true; |
6043 |
return true; |
| 6044 |
case AsmToken::Identifier: { |
6044 |
case AsmToken::Identifier: { |
| 6045 |
// If we've seen a branch mnemonic, the next operand must be a label. This |
6045 |
// If we've seen a branch mnemonic, the next operand must be a label. This |
| 6046 |
// is true even if the label is a register name. So "br r1" means branch to |
6046 |
// is true even if the label is a register name. So "br r1" means branch to |
| 6047 |
// label "r1". |
6047 |
// label "r1". |
| 6048 |
bool ExpectLabel = Mnemonic == "b" || Mnemonic == "bl"; |
6048 |
bool ExpectLabel = Mnemonic == "b" || Mnemonic == "bl"; |
| 6049 |
if (!ExpectLabel) { |
6049 |
if (!ExpectLabel) { |
| 6050 |
if (!tryParseRegisterWithWriteBack(Operands)) |
6050 |
if (!tryParseRegisterWithWriteBack(Operands)) |
| 6051 |
return false; |
6051 |
return false; |
| 6052 |
int Res = tryParseShiftRegister(Operands); |
6052 |
int Res = tryParseShiftRegister(Operands); |
| 6053 |
if (Res == 0) // success |
6053 |
if (Res == 0) // success |
| 6054 |
return false; |
6054 |
return false; |
| 6055 |
else if (Res == -1) // irrecoverable error |
6055 |
else if (Res == -1) // irrecoverable error |
| 6056 |
return true; |
6056 |
return true; |
| 6057 |
// If this is VMRS, check for the apsr_nzcv operand. |
6057 |
// If this is VMRS, check for the apsr_nzcv operand. |
| 6058 |
if (Mnemonic == "vmrs" && |
6058 |
if (Mnemonic == "vmrs" && |
| 6059 |
Parser.getTok().getString().equals_insensitive("apsr_nzcv")) { |
6059 |
Parser.getTok().getString().equals_insensitive("apsr_nzcv")) { |
| 6060 |
S = Parser.getTok().getLoc(); |
6060 |
S = Parser.getTok().getLoc(); |
| 6061 |
Parser.Lex(); |
6061 |
Parser.Lex(); |
| 6062 |
Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S)); |
6062 |
Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S)); |
| 6063 |
return false; |
6063 |
return false; |
| 6064 |
} |
6064 |
} |
| 6065 |
} |
6065 |
} |
| 6066 |
|
6066 |
|
| 6067 |
// Fall though for the Identifier case that is not a register or a |
6067 |
// Fall though for the Identifier case that is not a register or a |
| 6068 |
// special name. |
6068 |
// special name. |
| 6069 |
[[fallthrough]]; |
6069 |
[[fallthrough]]; |
| 6070 |
} |
6070 |
} |
| 6071 |
case AsmToken::LParen: // parenthesized expressions like (_strcmp-4) |
6071 |
case AsmToken::LParen: // parenthesized expressions like (_strcmp-4) |
| 6072 |
case AsmToken::Integer: // things like 1f and 2b as a branch targets |
6072 |
case AsmToken::Integer: // things like 1f and 2b as a branch targets |
| 6073 |
case AsmToken::String: // quoted label names. |
6073 |
case AsmToken::String: // quoted label names. |
| 6074 |
case AsmToken::Dot: { // . as a branch target |
6074 |
case AsmToken::Dot: { // . as a branch target |
| 6075 |
// This was not a register so parse other operands that start with an |
6075 |
// This was not a register so parse other operands that start with an |
| 6076 |
// identifier (like labels) as expressions and create them as immediates. |
6076 |
// identifier (like labels) as expressions and create them as immediates. |
| 6077 |
const MCExpr *IdVal; |
6077 |
const MCExpr *IdVal; |
| 6078 |
S = Parser.getTok().getLoc(); |
6078 |
S = Parser.getTok().getLoc(); |
| 6079 |
if (getParser().parseExpression(IdVal)) |
6079 |
if (getParser().parseExpression(IdVal)) |
| 6080 |
return true; |
6080 |
return true; |
| 6081 |
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
6081 |
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
| 6082 |
Operands.push_back(ARMOperand::CreateImm(IdVal, S, E)); |
6082 |
Operands.push_back(ARMOperand::CreateImm(IdVal, S, E)); |
| 6083 |
return false; |
6083 |
return false; |
| 6084 |
} |
6084 |
} |
| 6085 |
case AsmToken::LBrac: |
6085 |
case AsmToken::LBrac: |
| 6086 |
return parseMemory(Operands); |
6086 |
return parseMemory(Operands); |
| 6087 |
case AsmToken::LCurly: |
6087 |
case AsmToken::LCurly: |
| 6088 |
return parseRegisterList(Operands, !Mnemonic.startswith("clr")); |
6088 |
return parseRegisterList(Operands, !Mnemonic.startswith("clr")); |
| 6089 |
case AsmToken::Dollar: |
6089 |
case AsmToken::Dollar: |
| 6090 |
case AsmToken::Hash: { |
6090 |
case AsmToken::Hash: { |
| 6091 |
// #42 -> immediate |
6091 |
// #42 -> immediate |
| 6092 |
// $ 42 -> immediate |
6092 |
// $ 42 -> immediate |
| 6093 |
// $foo -> symbol name |
6093 |
// $foo -> symbol name |
| 6094 |
// $42 -> symbol name |
6094 |
// $42 -> symbol name |
| 6095 |
S = Parser.getTok().getLoc(); |
6095 |
S = Parser.getTok().getLoc(); |
| 6096 |
|
6096 |
|
| 6097 |
// Favor the interpretation of $-prefixed operands as symbol names. |
6097 |
// Favor the interpretation of $-prefixed operands as symbol names. |
| 6098 |
// Cases where immediates are explicitly expected are handled by their |
6098 |
// Cases where immediates are explicitly expected are handled by their |
| 6099 |
// specific ParseMethod implementations. |
6099 |
// specific ParseMethod implementations. |
| 6100 |
auto AdjacentToken = getLexer().peekTok(/*ShouldSkipSpace=*/false); |
6100 |
auto AdjacentToken = getLexer().peekTok(/*ShouldSkipSpace=*/false); |
| 6101 |
bool ExpectIdentifier = Parser.getTok().is(AsmToken::Dollar) && |
6101 |
bool ExpectIdentifier = Parser.getTok().is(AsmToken::Dollar) && |
| 6102 |
(AdjacentToken.is(AsmToken::Identifier) || |
6102 |
(AdjacentToken.is(AsmToken::Identifier) || |
| 6103 |
AdjacentToken.is(AsmToken::Integer)); |
6103 |
AdjacentToken.is(AsmToken::Integer)); |
| 6104 |
if (!ExpectIdentifier) { |
6104 |
if (!ExpectIdentifier) { |
| 6105 |
// Token is not part of identifier. Drop leading $ or # before parsing |
6105 |
// Token is not part of identifier. Drop leading $ or # before parsing |
| 6106 |
// expression. |
6106 |
// expression. |
| 6107 |
Parser.Lex(); |
6107 |
Parser.Lex(); |
| 6108 |
} |
6108 |
} |
| 6109 |
|
6109 |
|
| 6110 |
if (Parser.getTok().isNot(AsmToken::Colon)) { |
6110 |
if (Parser.getTok().isNot(AsmToken::Colon)) { |
| 6111 |
bool IsNegative = Parser.getTok().is(AsmToken::Minus); |
6111 |
bool IsNegative = Parser.getTok().is(AsmToken::Minus); |
| 6112 |
const MCExpr *ImmVal; |
6112 |
const MCExpr *ImmVal; |
| 6113 |
if (getParser().parseExpression(ImmVal)) |
6113 |
if (getParser().parseExpression(ImmVal)) |
| 6114 |
return true; |
6114 |
return true; |
| 6115 |
const MCConstantExpr *CE = dyn_cast(ImmVal); |
6115 |
const MCConstantExpr *CE = dyn_cast(ImmVal); |
| 6116 |
if (CE) { |
6116 |
if (CE) { |
| 6117 |
int32_t Val = CE->getValue(); |
6117 |
int32_t Val = CE->getValue(); |
| 6118 |
if (IsNegative && Val == 0) |
6118 |
if (IsNegative && Val == 0) |
| 6119 |
ImmVal = MCConstantExpr::create(std::numeric_limits::min(), |
6119 |
ImmVal = MCConstantExpr::create(std::numeric_limits::min(), |
| 6120 |
getContext()); |
6120 |
getContext()); |
| 6121 |
} |
6121 |
} |
| 6122 |
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
6122 |
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
| 6123 |
Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); |
6123 |
Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); |
| 6124 |
|
6124 |
|
| 6125 |
// There can be a trailing '!' on operands that we want as a separate |
6125 |
// There can be a trailing '!' on operands that we want as a separate |
| 6126 |
// '!' Token operand. Handle that here. For example, the compatibility |
6126 |
// '!' Token operand. Handle that here. For example, the compatibility |
| 6127 |
// alias for 'srsdb sp!, #imm' is 'srsdb #imm!'. |
6127 |
// alias for 'srsdb sp!, #imm' is 'srsdb #imm!'. |
| 6128 |
if (Parser.getTok().is(AsmToken::Exclaim)) { |
6128 |
if (Parser.getTok().is(AsmToken::Exclaim)) { |
| 6129 |
Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(), |
6129 |
Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(), |
| 6130 |
Parser.getTok().getLoc())); |
6130 |
Parser.getTok().getLoc())); |
| 6131 |
Parser.Lex(); // Eat exclaim token |
6131 |
Parser.Lex(); // Eat exclaim token |
| 6132 |
} |
6132 |
} |
| 6133 |
return false; |
6133 |
return false; |
| 6134 |
} |
6134 |
} |
| 6135 |
// w/ a ':' after the '#', it's just like a plain ':'. |
6135 |
// w/ a ':' after the '#', it's just like a plain ':'. |
| 6136 |
[[fallthrough]]; |
6136 |
[[fallthrough]]; |
| 6137 |
} |
6137 |
} |
| 6138 |
case AsmToken::Colon: { |
6138 |
case AsmToken::Colon: { |
| 6139 |
S = Parser.getTok().getLoc(); |
6139 |
S = Parser.getTok().getLoc(); |
| 6140 |
// ":lower16:", ":upper16:", ":lower0_7:", ":lower8_15:", ":upper0_7:" and |
6140 |
// ":lower16:", ":upper16:", ":lower0_7:", ":lower8_15:", ":upper0_7:" and |
| 6141 |
// ":upper8_15:", expression prefixes |
6141 |
// ":upper8_15:", expression prefixes |
| 6142 |
// FIXME: Check it's an expression prefix, |
6142 |
// FIXME: Check it's an expression prefix, |
| 6143 |
// e.g. (FOO - :lower16:BAR) isn't legal. |
6143 |
// e.g. (FOO - :lower16:BAR) isn't legal. |
| 6144 |
ARMMCExpr::VariantKind RefKind; |
6144 |
ARMMCExpr::VariantKind RefKind; |
| 6145 |
if (parsePrefix(RefKind)) |
6145 |
if (parsePrefix(RefKind)) |
| 6146 |
return true; |
6146 |
return true; |
| 6147 |
|
6147 |
|
| 6148 |
const MCExpr *SubExprVal; |
6148 |
const MCExpr *SubExprVal; |
| 6149 |
if (getParser().parseExpression(SubExprVal)) |
6149 |
if (getParser().parseExpression(SubExprVal)) |
| 6150 |
return true; |
6150 |
return true; |
| 6151 |
|
6151 |
|
| 6152 |
const MCExpr *ExprVal = ARMMCExpr::create(RefKind, SubExprVal, |
6152 |
const MCExpr *ExprVal = ARMMCExpr::create(RefKind, SubExprVal, |
| 6153 |
getContext()); |
6153 |
getContext()); |
| 6154 |
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
6154 |
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
| 6155 |
Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E)); |
6155 |
Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E)); |
| 6156 |
return false; |
6156 |
return false; |
| 6157 |
} |
6157 |
} |
| 6158 |
case AsmToken::Equal: { |
6158 |
case AsmToken::Equal: { |
| 6159 |
S = Parser.getTok().getLoc(); |
6159 |
S = Parser.getTok().getLoc(); |
| 6160 |
if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val) |
6160 |
if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val) |
| 6161 |
return Error(S, "unexpected token in operand"); |
6161 |
return Error(S, "unexpected token in operand"); |
| 6162 |
Parser.Lex(); // Eat '=' |
6162 |
Parser.Lex(); // Eat '=' |
| 6163 |
const MCExpr *SubExprVal; |
6163 |
const MCExpr *SubExprVal; |
| 6164 |
if (getParser().parseExpression(SubExprVal)) |
6164 |
if (getParser().parseExpression(SubExprVal)) |
| 6165 |
return true; |
6165 |
return true; |
| 6166 |
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
6166 |
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); |
| 6167 |
|
6167 |
|
| 6168 |
// execute-only: we assume that assembly programmers know what they are |
6168 |
// execute-only: we assume that assembly programmers know what they are |
| 6169 |
// doing and allow literal pool creation here |
6169 |
// doing and allow literal pool creation here |
| 6170 |
Operands.push_back(ARMOperand::CreateConstantPoolImm(SubExprVal, S, E)); |
6170 |
Operands.push_back(ARMOperand::CreateConstantPoolImm(SubExprVal, S, E)); |
| 6171 |
return false; |
6171 |
return false; |
| 6172 |
} |
6172 |
} |
| 6173 |
} |
6173 |
} |
| 6174 |
} |
6174 |
} |
| 6175 |
|
6175 |
|
| 6176 |
bool ARMAsmParser::parseImmExpr(int64_t &Out) { |
6176 |
bool ARMAsmParser::parseImmExpr(int64_t &Out) { |
| 6177 |
const MCExpr *Expr = nullptr; |
6177 |
const MCExpr *Expr = nullptr; |
| 6178 |
SMLoc L = getParser().getTok().getLoc(); |
6178 |
SMLoc L = getParser().getTok().getLoc(); |
| 6179 |
if (check(getParser().parseExpression(Expr), L, "expected expression")) |
6179 |
if (check(getParser().parseExpression(Expr), L, "expected expression")) |
| 6180 |
return true; |
6180 |
return true; |
| 6181 |
const MCConstantExpr *Value = dyn_cast_or_null(Expr); |
6181 |
const MCConstantExpr *Value = dyn_cast_or_null(Expr); |
| 6182 |
if (check(!Value, L, "expected constant expression")) |
6182 |
if (check(!Value, L, "expected constant expression")) |
| 6183 |
return true; |
6183 |
return true; |
| 6184 |
Out = Value->getValue(); |
6184 |
Out = Value->getValue(); |
| 6185 |
return false; |
6185 |
return false; |
| 6186 |
} |
6186 |
} |
| 6187 |
|
6187 |
|
| 6188 |
// parsePrefix - Parse ARM 16-bit relocations expression prefixes, i.e. |
6188 |
// parsePrefix - Parse ARM 16-bit relocations expression prefixes, i.e. |
| 6189 |
// :lower16: and :upper16: and Thumb 8-bit relocation expression prefixes, i.e. |
6189 |
// :lower16: and :upper16: and Thumb 8-bit relocation expression prefixes, i.e. |
| 6190 |
// :upper8_15:, :upper0_7:, :lower8_15: and :lower0_7: |
6190 |
// :upper8_15:, :upper0_7:, :lower8_15: and :lower0_7: |
| 6191 |
bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) { |
6191 |
bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) { |
| 6192 |
MCAsmParser &Parser = getParser(); |
6192 |
MCAsmParser &Parser = getParser(); |
| 6193 |
RefKind = ARMMCExpr::VK_ARM_None; |
6193 |
RefKind = ARMMCExpr::VK_ARM_None; |
| 6194 |
|
6194 |
|
| 6195 |
// consume an optional '#' (GNU compatibility) |
6195 |
// consume an optional '#' (GNU compatibility) |
| 6196 |
if (getLexer().is(AsmToken::Hash)) |
6196 |
if (getLexer().is(AsmToken::Hash)) |
| 6197 |
Parser.Lex(); |
6197 |
Parser.Lex(); |
| 6198 |
|
6198 |
|
| 6199 |
assert(getLexer().is(AsmToken::Colon) && "expected a :"); |
6199 |
assert(getLexer().is(AsmToken::Colon) && "expected a :"); |
| 6200 |
Parser.Lex(); // Eat ':' |
6200 |
Parser.Lex(); // Eat ':' |
| 6201 |
|
6201 |
|
| 6202 |
if (getLexer().isNot(AsmToken::Identifier)) { |
6202 |
if (getLexer().isNot(AsmToken::Identifier)) { |
| 6203 |
Error(Parser.getTok().getLoc(), "expected prefix identifier in operand"); |
6203 |
Error(Parser.getTok().getLoc(), "expected prefix identifier in operand"); |
| 6204 |
return true; |
6204 |
return true; |
| 6205 |
} |
6205 |
} |
| 6206 |
|
6206 |
|
| 6207 |
enum { |
6207 |
enum { |
| 6208 |
COFF = (1 << MCContext::IsCOFF), |
6208 |
COFF = (1 << MCContext::IsCOFF), |
| 6209 |
ELF = (1 << MCContext::IsELF), |
6209 |
ELF = (1 << MCContext::IsELF), |
| 6210 |
MACHO = (1 << MCContext::IsMachO), |
6210 |
MACHO = (1 << MCContext::IsMachO), |
| 6211 |
WASM = (1 << MCContext::IsWasm), |
6211 |
WASM = (1 << MCContext::IsWasm), |
| 6212 |
}; |
6212 |
}; |
| 6213 |
static const struct PrefixEntry { |
6213 |
static const struct PrefixEntry { |
| 6214 |
const char *Spelling; |
6214 |
const char *Spelling; |
| 6215 |
ARMMCExpr::VariantKind VariantKind; |
6215 |
ARMMCExpr::VariantKind VariantKind; |
| 6216 |
uint8_t SupportedFormats; |
6216 |
uint8_t SupportedFormats; |
| 6217 |
} PrefixEntries[] = { |
6217 |
} PrefixEntries[] = { |
| 6218 |
{"upper16", ARMMCExpr::VK_ARM_HI16, COFF | ELF | MACHO}, |
6218 |
{"upper16", ARMMCExpr::VK_ARM_HI16, COFF | ELF | MACHO}, |
| 6219 |
{"lower16", ARMMCExpr::VK_ARM_LO16, COFF | ELF | MACHO}, |
6219 |
{"lower16", ARMMCExpr::VK_ARM_LO16, COFF | ELF | MACHO}, |
| 6220 |
{"upper8_15", ARMMCExpr::VK_ARM_HI_8_15, ELF}, |
6220 |
{"upper8_15", ARMMCExpr::VK_ARM_HI_8_15, ELF}, |
| 6221 |
{"upper0_7", ARMMCExpr::VK_ARM_HI_0_7, ELF}, |
6221 |
{"upper0_7", ARMMCExpr::VK_ARM_HI_0_7, ELF}, |
| 6222 |
{"lower8_15", ARMMCExpr::VK_ARM_LO_8_15, ELF}, |
6222 |
{"lower8_15", ARMMCExpr::VK_ARM_LO_8_15, ELF}, |
| 6223 |
{"lower0_7", ARMMCExpr::VK_ARM_LO_0_7, ELF}, |
6223 |
{"lower0_7", ARMMCExpr::VK_ARM_LO_0_7, ELF}, |
| 6224 |
}; |
6224 |
}; |
| 6225 |
|
6225 |
|
| 6226 |
StringRef IDVal = Parser.getTok().getIdentifier(); |
6226 |
StringRef IDVal = Parser.getTok().getIdentifier(); |
| 6227 |
|
6227 |
|
| 6228 |
const auto &Prefix = |
6228 |
const auto &Prefix = |
| 6229 |
llvm::find_if(PrefixEntries, [&IDVal](const PrefixEntry &PE) { |
6229 |
llvm::find_if(PrefixEntries, [&IDVal](const PrefixEntry &PE) { |
| 6230 |
return PE.Spelling == IDVal; |
6230 |
return PE.Spelling == IDVal; |
| 6231 |
}); |
6231 |
}); |
| 6232 |
if (Prefix == std::end(PrefixEntries)) { |
6232 |
if (Prefix == std::end(PrefixEntries)) { |
| 6233 |
Error(Parser.getTok().getLoc(), "unexpected prefix in operand"); |
6233 |
Error(Parser.getTok().getLoc(), "unexpected prefix in operand"); |
| 6234 |
return true; |
6234 |
return true; |
| 6235 |
} |
6235 |
} |
| 6236 |
|
6236 |
|
| 6237 |
uint8_t CurrentFormat; |
6237 |
uint8_t CurrentFormat; |
| 6238 |
switch (getContext().getObjectFileType()) { |
6238 |
switch (getContext().getObjectFileType()) { |
| 6239 |
case MCContext::IsMachO: |
6239 |
case MCContext::IsMachO: |
| 6240 |
CurrentFormat = MACHO; |
6240 |
CurrentFormat = MACHO; |
| 6241 |
break; |
6241 |
break; |
| 6242 |
case MCContext::IsELF: |
6242 |
case MCContext::IsELF: |
| 6243 |
CurrentFormat = ELF; |
6243 |
CurrentFormat = ELF; |
| 6244 |
break; |
6244 |
break; |
| 6245 |
case MCContext::IsCOFF: |
6245 |
case MCContext::IsCOFF: |
| 6246 |
CurrentFormat = COFF; |
6246 |
CurrentFormat = COFF; |
| 6247 |
break; |
6247 |
break; |
| 6248 |
case MCContext::IsWasm: |
6248 |
case MCContext::IsWasm: |
| 6249 |
CurrentFormat = WASM; |
6249 |
CurrentFormat = WASM; |
| 6250 |
break; |
6250 |
break; |
| 6251 |
case MCContext::IsGOFF: |
6251 |
case MCContext::IsGOFF: |
| 6252 |
case MCContext::IsSPIRV: |
6252 |
case MCContext::IsSPIRV: |
| 6253 |
case MCContext::IsXCOFF: |
6253 |
case MCContext::IsXCOFF: |
| 6254 |
case MCContext::IsDXContainer: |
6254 |
case MCContext::IsDXContainer: |
| 6255 |
llvm_unreachable("unexpected object format"); |
6255 |
llvm_unreachable("unexpected object format"); |
| 6256 |
break; |
6256 |
break; |
| 6257 |
} |
6257 |
} |
| 6258 |
|
6258 |
|
| 6259 |
if (~Prefix->SupportedFormats & CurrentFormat) { |
6259 |
if (~Prefix->SupportedFormats & CurrentFormat) { |
| 6260 |
Error(Parser.getTok().getLoc(), |
6260 |
Error(Parser.getTok().getLoc(), |
| 6261 |
"cannot represent relocation in the current file format"); |
6261 |
"cannot represent relocation in the current file format"); |
| 6262 |
return true; |
6262 |
return true; |
| 6263 |
} |
6263 |
} |
| 6264 |
|
6264 |
|
| 6265 |
RefKind = Prefix->VariantKind; |
6265 |
RefKind = Prefix->VariantKind; |
| 6266 |
Parser.Lex(); |
6266 |
Parser.Lex(); |
| 6267 |
|
6267 |
|
| 6268 |
if (getLexer().isNot(AsmToken::Colon)) { |
6268 |
if (getLexer().isNot(AsmToken::Colon)) { |
| 6269 |
Error(Parser.getTok().getLoc(), "unexpected token after prefix"); |
6269 |
Error(Parser.getTok().getLoc(), "unexpected token after prefix"); |
| 6270 |
return true; |
6270 |
return true; |
| 6271 |
} |
6271 |
} |
| 6272 |
Parser.Lex(); // Eat the last ':' |
6272 |
Parser.Lex(); // Eat the last ':' |
| 6273 |
|
6273 |
|
| 6274 |
// consume an optional trailing '#' (GNU compatibility) bla |
6274 |
// consume an optional trailing '#' (GNU compatibility) bla |
| 6275 |
parseOptionalToken(AsmToken::Hash); |
6275 |
parseOptionalToken(AsmToken::Hash); |
| 6276 |
|
6276 |
|
| 6277 |
return false; |
6277 |
return false; |
| 6278 |
} |
6278 |
} |
| 6279 |
|
6279 |
|
| 6280 |
/// Given a mnemonic, split out possible predication code and carry |
6280 |
/// Given a mnemonic, split out possible predication code and carry |
| 6281 |
/// setting letters to form a canonical mnemonic and flags. |
6281 |
/// setting letters to form a canonical mnemonic and flags. |
| 6282 |
// |
6282 |
// |
| 6283 |
// FIXME: Would be nice to autogen this. |
6283 |
// FIXME: Would be nice to autogen this. |
| 6284 |
// FIXME: This is a bit of a maze of special cases. |
6284 |
// FIXME: This is a bit of a maze of special cases. |
| 6285 |
StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, |
6285 |
StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, |
| 6286 |
StringRef ExtraToken, |
6286 |
StringRef ExtraToken, |
| 6287 |
unsigned &PredicationCode, |
6287 |
unsigned &PredicationCode, |
| 6288 |
unsigned &VPTPredicationCode, |
6288 |
unsigned &VPTPredicationCode, |
| 6289 |
bool &CarrySetting, |
6289 |
bool &CarrySetting, |
| 6290 |
unsigned &ProcessorIMod, |
6290 |
unsigned &ProcessorIMod, |
| 6291 |
StringRef &ITMask) { |
6291 |
StringRef &ITMask) { |
| 6292 |
PredicationCode = ARMCC::AL; |
6292 |
PredicationCode = ARMCC::AL; |
| 6293 |
VPTPredicationCode = ARMVCC::None; |
6293 |
VPTPredicationCode = ARMVCC::None; |
| 6294 |
CarrySetting = false; |
6294 |
CarrySetting = false; |
| 6295 |
ProcessorIMod = 0; |
6295 |
ProcessorIMod = 0; |
| 6296 |
|
6296 |
|
| 6297 |
// Ignore some mnemonics we know aren't predicated forms. |
6297 |
// Ignore some mnemonics we know aren't predicated forms. |
| 6298 |
// |
6298 |
// |
| 6299 |
// FIXME: Would be nice to autogen this. |
6299 |
// FIXME: Would be nice to autogen this. |
| 6300 |
if ((Mnemonic == "movs" && isThumb()) || |
6300 |
if ((Mnemonic == "movs" && isThumb()) || |
| 6301 |
Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" || |
6301 |
Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" || |
| 6302 |
Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" || |
6302 |
Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" || |
| 6303 |
Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" || |
6303 |
Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" || |
| 6304 |
Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" || |
6304 |
Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" || |
| 6305 |
Mnemonic == "vaclt" || Mnemonic == "vacle" || Mnemonic == "hlt" || |
6305 |
Mnemonic == "vaclt" || Mnemonic == "vacle" || Mnemonic == "hlt" || |
| 6306 |
Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" || |
6306 |
Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" || |
| 6307 |
Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || |
6307 |
Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" || |
| 6308 |
Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" || |
6308 |
Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" || |
| 6309 |
Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || |
6309 |
Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || |
| 6310 |
Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || |
6310 |
Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || |
| 6311 |
Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" || |
6311 |
Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" || |
| 6312 |
Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic == "hvc" || |
6312 |
Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic == "hvc" || |
| 6313 |
Mnemonic.startswith("vsel") || Mnemonic == "vins" || Mnemonic == "vmovx" || |
6313 |
Mnemonic.startswith("vsel") || Mnemonic == "vins" || Mnemonic == "vmovx" || |
| 6314 |
Mnemonic == "bxns" || Mnemonic == "blxns" || |
6314 |
Mnemonic == "bxns" || Mnemonic == "blxns" || |
| 6315 |
Mnemonic == "vdot" || Mnemonic == "vmmla" || |
6315 |
Mnemonic == "vdot" || Mnemonic == "vmmla" || |
| 6316 |
Mnemonic == "vudot" || Mnemonic == "vsdot" || |
6316 |
Mnemonic == "vudot" || Mnemonic == "vsdot" || |
| 6317 |
Mnemonic == "vcmla" || Mnemonic == "vcadd" || |
6317 |
Mnemonic == "vcmla" || Mnemonic == "vcadd" || |
| 6318 |
Mnemonic == "vfmal" || Mnemonic == "vfmsl" || |
6318 |
Mnemonic == "vfmal" || Mnemonic == "vfmsl" || |
| 6319 |
Mnemonic == "wls" || Mnemonic == "le" || Mnemonic == "dls" || |
6319 |
Mnemonic == "wls" || Mnemonic == "le" || Mnemonic == "dls" || |
| 6320 |
Mnemonic == "csel" || Mnemonic == "csinc" || |
6320 |
Mnemonic == "csel" || Mnemonic == "csinc" || |
| 6321 |
Mnemonic == "csinv" || Mnemonic == "csneg" || Mnemonic == "cinc" || |
6321 |
Mnemonic == "csinv" || Mnemonic == "csneg" || Mnemonic == "cinc" || |
| 6322 |
Mnemonic == "cinv" || Mnemonic == "cneg" || Mnemonic == "cset" || |
6322 |
Mnemonic == "cinv" || Mnemonic == "cneg" || Mnemonic == "cset" || |
| 6323 |
Mnemonic == "csetm" || |
6323 |
Mnemonic == "csetm" || |
| 6324 |
Mnemonic == "aut" || Mnemonic == "pac" || Mnemonic == "pacbti" || |
6324 |
Mnemonic == "aut" || Mnemonic == "pac" || Mnemonic == "pacbti" || |
| 6325 |
Mnemonic == "bti") |
6325 |
Mnemonic == "bti") |
| 6326 |
return Mnemonic; |
6326 |
return Mnemonic; |
| 6327 |
|
6327 |
|
| 6328 |
// First, split out any predication code. Ignore mnemonics we know aren't |
6328 |
// First, split out any predication code. Ignore mnemonics we know aren't |
| 6329 |
// predicated but do have a carry-set and so weren't caught above. |
6329 |
// predicated but do have a carry-set and so weren't caught above. |
| 6330 |
if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" && |
6330 |
if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" && |
| 6331 |
Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" && |
6331 |
Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" && |
| 6332 |
Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" && |
6332 |
Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" && |
| 6333 |
Mnemonic != "sbcs" && Mnemonic != "rscs" && |
6333 |
Mnemonic != "sbcs" && Mnemonic != "rscs" && |
| 6334 |
!(hasMVE() && |
6334 |
!(hasMVE() && |
| 6335 |
(Mnemonic == "vmine" || |
6335 |
(Mnemonic == "vmine" || |
| 6336 |
Mnemonic == "vshle" || Mnemonic == "vshlt" || Mnemonic == "vshllt" || |
6336 |
Mnemonic == "vshle" || Mnemonic == "vshlt" || Mnemonic == "vshllt" || |
| 6337 |
Mnemonic == "vrshle" || Mnemonic == "vrshlt" || |
6337 |
Mnemonic == "vrshle" || Mnemonic == "vrshlt" || |
| 6338 |
Mnemonic == "vmvne" || Mnemonic == "vorne" || |
6338 |
Mnemonic == "vmvne" || Mnemonic == "vorne" || |
| 6339 |
Mnemonic == "vnege" || Mnemonic == "vnegt" || |
6339 |
Mnemonic == "vnege" || Mnemonic == "vnegt" || |
| 6340 |
Mnemonic == "vmule" || Mnemonic == "vmult" || |
6340 |
Mnemonic == "vmule" || Mnemonic == "vmult" || |
| 6341 |
Mnemonic == "vrintne" || |
6341 |
Mnemonic == "vrintne" || |
| 6342 |
Mnemonic == "vcmult" || Mnemonic == "vcmule" || |
6342 |
Mnemonic == "vcmult" || Mnemonic == "vcmule" || |
| 6343 |
Mnemonic == "vpsele" || Mnemonic == "vpselt" || |
6343 |
Mnemonic == "vpsele" || Mnemonic == "vpselt" || |
| 6344 |
Mnemonic.startswith("vq")))) { |
6344 |
Mnemonic.startswith("vq")))) { |
| 6345 |
unsigned CC = ARMCondCodeFromString(Mnemonic.substr(Mnemonic.size()-2)); |
6345 |
unsigned CC = ARMCondCodeFromString(Mnemonic.substr(Mnemonic.size()-2)); |
| 6346 |
if (CC != ~0U) { |
6346 |
if (CC != ~0U) { |
| 6347 |
Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2); |
6347 |
Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2); |
| 6348 |
PredicationCode = CC; |
6348 |
PredicationCode = CC; |
| 6349 |
} |
6349 |
} |
| 6350 |
} |
6350 |
} |
| 6351 |
|
6351 |
|
| 6352 |
// Next, determine if we have a carry setting bit. We explicitly ignore all |
6352 |
// Next, determine if we have a carry setting bit. We explicitly ignore all |
| 6353 |
// the instructions we know end in 's'. |
6353 |
// the instructions we know end in 's'. |
| 6354 |
if (Mnemonic.endswith("s") && |
6354 |
if (Mnemonic.endswith("s") && |
| 6355 |
!(Mnemonic == "cps" || Mnemonic == "mls" || |
6355 |
!(Mnemonic == "cps" || Mnemonic == "mls" || |
| 6356 |
Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" || |
6356 |
Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" || |
| 6357 |
Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" || |
6357 |
Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" || |
| 6358 |
Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" || |
6358 |
Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" || |
| 6359 |
Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" || |
6359 |
Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" || |
| 6360 |
Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" || |
6360 |
Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" || |
| 6361 |
Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" || |
6361 |
Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" || |
| 6362 |
Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" || |
6362 |
Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" || |
| 6363 |
Mnemonic == "vfms" || Mnemonic == "vfnms" || Mnemonic == "fconsts" || |
6363 |
Mnemonic == "vfms" || Mnemonic == "vfnms" || Mnemonic == "fconsts" || |
| 6364 |
Mnemonic == "bxns" || Mnemonic == "blxns" || Mnemonic == "vfmas" || |
6364 |
Mnemonic == "bxns" || Mnemonic == "blxns" || Mnemonic == "vfmas" || |
| 6365 |
Mnemonic == "vmlas" || |
6365 |
Mnemonic == "vmlas" || |
| 6366 |
(Mnemonic == "movs" && isThumb()))) { |
6366 |
(Mnemonic == "movs" && isThumb()))) { |
| 6367 |
Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1); |
6367 |
Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1); |
| 6368 |
CarrySetting = true; |
6368 |
CarrySetting = true; |
| 6369 |
} |
6369 |
} |
| 6370 |
|
6370 |
|
| 6371 |
// The "cps" instruction can have a interrupt mode operand which is glued into |
6371 |
// The "cps" instruction can have a interrupt mode operand which is glued into |
| 6372 |
// the mnemonic. Check if this is the case, split it and parse the imod op |
6372 |
// the mnemonic. Check if this is the case, split it and parse the imod op |
| 6373 |
if (Mnemonic.startswith("cps")) { |
6373 |
if (Mnemonic.startswith("cps")) { |
| 6374 |
// Split out any imod code. |
6374 |
// Split out any imod code. |
| 6375 |
unsigned IMod = |
6375 |
unsigned IMod = |
| 6376 |
StringSwitch(Mnemonic.substr(Mnemonic.size()-2, 2)) |
6376 |
StringSwitch(Mnemonic.substr(Mnemonic.size()-2, 2)) |
| 6377 |
.Case("ie", ARM_PROC::IE) |
6377 |
.Case("ie", ARM_PROC::IE) |
| 6378 |
.Case("id", ARM_PROC::ID) |
6378 |
.Case("id", ARM_PROC::ID) |
| 6379 |
.Default(~0U); |
6379 |
.Default(~0U); |
| 6380 |
if (IMod != ~0U) { |
6380 |
if (IMod != ~0U) { |
| 6381 |
Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2); |
6381 |
Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2); |
| 6382 |
ProcessorIMod = IMod; |
6382 |
ProcessorIMod = IMod; |
| 6383 |
} |
6383 |
} |
| 6384 |
} |
6384 |
} |
| 6385 |
|
6385 |
|
| 6386 |
if (isMnemonicVPTPredicable(Mnemonic, ExtraToken) && Mnemonic != "vmovlt" && |
6386 |
if (isMnemonicVPTPredicable(Mnemonic, ExtraToken) && Mnemonic != "vmovlt" && |
| 6387 |
Mnemonic != "vshllt" && Mnemonic != "vrshrnt" && Mnemonic != "vshrnt" && |
6387 |
Mnemonic != "vshllt" && Mnemonic != "vrshrnt" && Mnemonic != "vshrnt" && |
| 6388 |
Mnemonic != "vqrshrunt" && Mnemonic != "vqshrunt" && |
6388 |
Mnemonic != "vqrshrunt" && Mnemonic != "vqshrunt" && |
| 6389 |
Mnemonic != "vqrshrnt" && Mnemonic != "vqshrnt" && Mnemonic != "vmullt" && |
6389 |
Mnemonic != "vqrshrnt" && Mnemonic != "vqshrnt" && Mnemonic != "vmullt" && |
| 6390 |
Mnemonic != "vqmovnt" && Mnemonic != "vqmovunt" && |
6390 |
Mnemonic != "vqmovnt" && Mnemonic != "vqmovunt" && |
| 6391 |
Mnemonic != "vqmovnt" && Mnemonic != "vmovnt" && Mnemonic != "vqdmullt" && |
6391 |
Mnemonic != "vqmovnt" && Mnemonic != "vmovnt" && Mnemonic != "vqdmullt" && |
| 6392 |
Mnemonic != "vpnot" && Mnemonic != "vcvtt" && Mnemonic != "vcvt") { |
6392 |
Mnemonic != "vpnot" && Mnemonic != "vcvtt" && Mnemonic != "vcvt") { |
| 6393 |
unsigned CC = ARMVectorCondCodeFromString(Mnemonic.substr(Mnemonic.size()-1)); |
6393 |
unsigned CC = ARMVectorCondCodeFromString(Mnemonic.substr(Mnemonic.size()-1)); |
| 6394 |
if (CC != ~0U) { |
6394 |
if (CC != ~0U) { |
| 6395 |
Mnemonic = Mnemonic.slice(0, Mnemonic.size()-1); |
6395 |
Mnemonic = Mnemonic.slice(0, Mnemonic.size()-1); |
| 6396 |
VPTPredicationCode = CC; |
6396 |
VPTPredicationCode = CC; |
| 6397 |
} |
6397 |
} |
| 6398 |
return Mnemonic; |
6398 |
return Mnemonic; |
| 6399 |
} |
6399 |
} |
| 6400 |
|
6400 |
|
| 6401 |
// The "it" instruction has the condition mask on the end of the mnemonic. |
6401 |
// The "it" instruction has the condition mask on the end of the mnemonic. |
| 6402 |
if (Mnemonic.startswith("it")) { |
6402 |
if (Mnemonic.startswith("it")) { |
| 6403 |
ITMask = Mnemonic.slice(2, Mnemonic.size()); |
6403 |
ITMask = Mnemonic.slice(2, Mnemonic.size()); |
| 6404 |
Mnemonic = Mnemonic.slice(0, 2); |
6404 |
Mnemonic = Mnemonic.slice(0, 2); |
| 6405 |
} |
6405 |
} |
| 6406 |
|
6406 |
|
| 6407 |
if (Mnemonic.startswith("vpst")) { |
6407 |
if (Mnemonic.startswith("vpst")) { |
| 6408 |
ITMask = Mnemonic.slice(4, Mnemonic.size()); |
6408 |
ITMask = Mnemonic.slice(4, Mnemonic.size()); |
| 6409 |
Mnemonic = Mnemonic.slice(0, 4); |
6409 |
Mnemonic = Mnemonic.slice(0, 4); |
| 6410 |
} |
6410 |
} |
| 6411 |
else if (Mnemonic.startswith("vpt")) { |
6411 |
else if (Mnemonic.startswith("vpt")) { |
| 6412 |
ITMask = Mnemonic.slice(3, Mnemonic.size()); |
6412 |
ITMask = Mnemonic.slice(3, Mnemonic.size()); |
| 6413 |
Mnemonic = Mnemonic.slice(0, 3); |
6413 |
Mnemonic = Mnemonic.slice(0, 3); |
| 6414 |
} |
6414 |
} |
| 6415 |
|
6415 |
|
| 6416 |
return Mnemonic; |
6416 |
return Mnemonic; |
| 6417 |
} |
6417 |
} |
| 6418 |
|
6418 |
|
| 6419 |
/// Given a canonical mnemonic, determine if the instruction ever allows |
6419 |
/// Given a canonical mnemonic, determine if the instruction ever allows |
| 6420 |
/// inclusion of carry set or predication code operands. |
6420 |
/// inclusion of carry set or predication code operands. |
| 6421 |
// |
6421 |
// |
| 6422 |
// FIXME: It would be nice to autogen this. |
6422 |
// FIXME: It would be nice to autogen this. |
| 6423 |
void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic, |
6423 |
void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic, |
| 6424 |
StringRef ExtraToken, |
6424 |
StringRef ExtraToken, |
| 6425 |
StringRef FullInst, |
6425 |
StringRef FullInst, |
| 6426 |
bool &CanAcceptCarrySet, |
6426 |
bool &CanAcceptCarrySet, |
| 6427 |
bool &CanAcceptPredicationCode, |
6427 |
bool &CanAcceptPredicationCode, |
| 6428 |
bool &CanAcceptVPTPredicationCode) { |
6428 |
bool &CanAcceptVPTPredicationCode) { |
| 6429 |
CanAcceptVPTPredicationCode = isMnemonicVPTPredicable(Mnemonic, ExtraToken); |
6429 |
CanAcceptVPTPredicationCode = isMnemonicVPTPredicable(Mnemonic, ExtraToken); |
| 6430 |
|
6430 |
|
| 6431 |
CanAcceptCarrySet = |
6431 |
CanAcceptCarrySet = |
| 6432 |
Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" || |
6432 |
Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" || |
| 6433 |
Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" || |
6433 |
Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" || |
| 6434 |
Mnemonic == "add" || Mnemonic == "adc" || Mnemonic == "mul" || |
6434 |
Mnemonic == "add" || Mnemonic == "adc" || Mnemonic == "mul" || |
| 6435 |
Mnemonic == "bic" || Mnemonic == "asr" || Mnemonic == "orr" || |
6435 |
Mnemonic == "bic" || Mnemonic == "asr" || Mnemonic == "orr" || |
| 6436 |
Mnemonic == "mvn" || Mnemonic == "rsb" || Mnemonic == "rsc" || |
6436 |
Mnemonic == "mvn" || Mnemonic == "rsb" || Mnemonic == "rsc" || |
| 6437 |
Mnemonic == "orn" || Mnemonic == "sbc" || Mnemonic == "eor" || |
6437 |
Mnemonic == "orn" || Mnemonic == "sbc" || Mnemonic == "eor" || |
| 6438 |
Mnemonic == "neg" || Mnemonic == "vfm" || Mnemonic == "vfnm" || |
6438 |
Mnemonic == "neg" || Mnemonic == "vfm" || Mnemonic == "vfnm" || |
| 6439 |
(!isThumb() && |
6439 |
(!isThumb() && |
| 6440 |
(Mnemonic == "smull" || Mnemonic == "mov" || Mnemonic == "mla" || |
6440 |
(Mnemonic == "smull" || Mnemonic == "mov" || Mnemonic == "mla" || |
| 6441 |
Mnemonic == "smlal" || Mnemonic == "umlal" || Mnemonic == "umull")); |
6441 |
Mnemonic == "smlal" || Mnemonic == "umlal" || Mnemonic == "umull")); |
| 6442 |
|
6442 |
|
| 6443 |
if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || |
6443 |
if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || |
| 6444 |
Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || |
6444 |
Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || |
| 6445 |
Mnemonic == "trap" || Mnemonic == "hlt" || Mnemonic == "udf" || |
6445 |
Mnemonic == "trap" || Mnemonic == "hlt" || Mnemonic == "udf" || |
| 6446 |
Mnemonic.startswith("crc32") || Mnemonic.startswith("cps") || |
6446 |
Mnemonic.startswith("crc32") || Mnemonic.startswith("cps") || |
| 6447 |
Mnemonic.startswith("vsel") || Mnemonic == "vmaxnm" || |
6447 |
Mnemonic.startswith("vsel") || Mnemonic == "vmaxnm" || |
| 6448 |
Mnemonic == "vminnm" || Mnemonic == "vcvta" || Mnemonic == "vcvtn" || |
6448 |
Mnemonic == "vminnm" || Mnemonic == "vcvta" || Mnemonic == "vcvtn" || |
| 6449 |
Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Mnemonic == "vrinta" || |
6449 |
Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Mnemonic == "vrinta" || |
| 6450 |
Mnemonic == "vrintn" || Mnemonic == "vrintp" || Mnemonic == "vrintm" || |
6450 |
Mnemonic == "vrintn" || Mnemonic == "vrintp" || Mnemonic == "vrintm" || |
| 6451 |
Mnemonic.startswith("aes") || Mnemonic == "hvc" || Mnemonic == "setpan" || |
6451 |
Mnemonic.startswith("aes") || Mnemonic == "hvc" || Mnemonic == "setpan" || |
| 6452 |
Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") || |
6452 |
Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") || |
| 6453 |
(FullInst.startswith("vmull") && FullInst.endswith(".p64")) || |
6453 |
(FullInst.startswith("vmull") && FullInst.endswith(".p64")) || |
| 6454 |
Mnemonic == "vmovx" || Mnemonic == "vins" || |
6454 |
Mnemonic == "vmovx" || Mnemonic == "vins" || |
| 6455 |
Mnemonic == "vudot" || Mnemonic == "vsdot" || |
6455 |
Mnemonic == "vudot" || Mnemonic == "vsdot" || |
| 6456 |
Mnemonic == "vcmla" || Mnemonic == "vcadd" || |
6456 |
Mnemonic == "vcmla" || Mnemonic == "vcadd" || |
| 6457 |
Mnemonic == "vfmal" || Mnemonic == "vfmsl" || |
6457 |
Mnemonic == "vfmal" || Mnemonic == "vfmsl" || |
| 6458 |
Mnemonic == "vfmat" || Mnemonic == "vfmab" || |
6458 |
Mnemonic == "vfmat" || Mnemonic == "vfmab" || |
| 6459 |
Mnemonic == "vdot" || Mnemonic == "vmmla" || |
6459 |
Mnemonic == "vdot" || Mnemonic == "vmmla" || |
| 6460 |
Mnemonic == "sb" || Mnemonic == "ssbb" || |
6460 |
Mnemonic == "sb" || Mnemonic == "ssbb" || |
| 6461 |
Mnemonic == "pssbb" || Mnemonic == "vsmmla" || |
6461 |
Mnemonic == "pssbb" || Mnemonic == "vsmmla" || |
| 6462 |
Mnemonic == "vummla" || Mnemonic == "vusmmla" || |
6462 |
Mnemonic == "vummla" || Mnemonic == "vusmmla" || |
| 6463 |
Mnemonic == "vusdot" || Mnemonic == "vsudot" || |
6463 |
Mnemonic == "vusdot" || Mnemonic == "vsudot" || |
| 6464 |
Mnemonic == "bfcsel" || Mnemonic == "wls" || |
6464 |
Mnemonic == "bfcsel" || Mnemonic == "wls" || |
| 6465 |
Mnemonic == "dls" || Mnemonic == "le" || Mnemonic == "csel" || |
6465 |
Mnemonic == "dls" || Mnemonic == "le" || Mnemonic == "csel" || |
| 6466 |
Mnemonic == "csinc" || Mnemonic == "csinv" || Mnemonic == "csneg" || |
6466 |
Mnemonic == "csinc" || Mnemonic == "csinv" || Mnemonic == "csneg" || |
| 6467 |
Mnemonic == "cinc" || Mnemonic == "cinv" || Mnemonic == "cneg" || |
6467 |
Mnemonic == "cinc" || Mnemonic == "cinv" || Mnemonic == "cneg" || |
| 6468 |
Mnemonic == "cset" || Mnemonic == "csetm" || |
6468 |
Mnemonic == "cset" || Mnemonic == "csetm" || |
| 6469 |
(hasCDE() && MS.isCDEInstr(Mnemonic) && |
6469 |
(hasCDE() && MS.isCDEInstr(Mnemonic) && |
| 6470 |
!MS.isITPredicableCDEInstr(Mnemonic)) || |
6470 |
!MS.isITPredicableCDEInstr(Mnemonic)) || |
| 6471 |
Mnemonic.startswith("vpt") || Mnemonic.startswith("vpst") || |
6471 |
Mnemonic.startswith("vpt") || Mnemonic.startswith("vpst") || |
| 6472 |
Mnemonic == "pac" || Mnemonic == "pacbti" || Mnemonic == "aut" || |
6472 |
Mnemonic == "pac" || Mnemonic == "pacbti" || Mnemonic == "aut" || |
| 6473 |
Mnemonic == "bti" || |
6473 |
Mnemonic == "bti" || |
| 6474 |
(hasMVE() && |
6474 |
(hasMVE() && |
| 6475 |
(Mnemonic.startswith("vst2") || Mnemonic.startswith("vld2") || |
6475 |
(Mnemonic.startswith("vst2") || Mnemonic.startswith("vld2") || |
| 6476 |
Mnemonic.startswith("vst4") || Mnemonic.startswith("vld4") || |
6476 |
Mnemonic.startswith("vst4") || Mnemonic.startswith("vld4") || |
| 6477 |
Mnemonic.startswith("wlstp") || Mnemonic.startswith("dlstp") || |
6477 |
Mnemonic.startswith("wlstp") || Mnemonic.startswith("dlstp") || |
| 6478 |
Mnemonic.startswith("letp")))) { |
6478 |
Mnemonic.startswith("letp")))) { |
| 6479 |
// These mnemonics are never predicable |
6479 |
// These mnemonics are never predicable |
| 6480 |
CanAcceptPredicationCode = false; |
6480 |
CanAcceptPredicationCode = false; |
| 6481 |
} else if (!isThumb()) { |
6481 |
} else if (!isThumb()) { |
| 6482 |
// Some instructions are only predicable in Thumb mode |
6482 |
// Some instructions are only predicable in Thumb mode |
| 6483 |
CanAcceptPredicationCode = |
6483 |
CanAcceptPredicationCode = |
| 6484 |
Mnemonic != "cdp2" && Mnemonic != "clrex" && Mnemonic != "mcr2" && |
6484 |
Mnemonic != "cdp2" && Mnemonic != "clrex" && Mnemonic != "mcr2" && |
| 6485 |
Mnemonic != "mcrr2" && Mnemonic != "mrc2" && Mnemonic != "mrrc2" && |
6485 |
Mnemonic != "mcrr2" && Mnemonic != "mrc2" && Mnemonic != "mrrc2" && |
| 6486 |
Mnemonic != "dmb" && Mnemonic != "dfb" && Mnemonic != "dsb" && |
6486 |
Mnemonic != "dmb" && Mnemonic != "dfb" && Mnemonic != "dsb" && |
| 6487 |
Mnemonic != "isb" && Mnemonic != "pld" && Mnemonic != "pli" && |
6487 |
Mnemonic != "isb" && Mnemonic != "pld" && Mnemonic != "pli" && |
| 6488 |
Mnemonic != "pldw" && Mnemonic != "ldc2" && Mnemonic != "ldc2l" && |
6488 |
Mnemonic != "pldw" && Mnemonic != "ldc2" && Mnemonic != "ldc2l" && |
| 6489 |
Mnemonic != "stc2" && Mnemonic != "stc2l" && |
6489 |
Mnemonic != "stc2" && Mnemonic != "stc2l" && |
| 6490 |
Mnemonic != "tsb" && |
6490 |
Mnemonic != "tsb" && |
| 6491 |
!Mnemonic.startswith("rfe") && !Mnemonic.startswith("srs"); |
6491 |
!Mnemonic.startswith("rfe") && !Mnemonic.startswith("srs"); |
| 6492 |
} else if (isThumbOne()) { |
6492 |
} else if (isThumbOne()) { |
| 6493 |
if (hasV6MOps()) |
6493 |
if (hasV6MOps()) |
| 6494 |
CanAcceptPredicationCode = Mnemonic != "movs"; |
6494 |
CanAcceptPredicationCode = Mnemonic != "movs"; |
| 6495 |
else |
6495 |
else |
| 6496 |
CanAcceptPredicationCode = Mnemonic != "nop" && Mnemonic != "movs"; |
6496 |
CanAcceptPredicationCode = Mnemonic != "nop" && Mnemonic != "movs"; |
| 6497 |
} else |
6497 |
} else |
| 6498 |
CanAcceptPredicationCode = true; |
6498 |
CanAcceptPredicationCode = true; |
| 6499 |
} |
6499 |
} |
| 6500 |
|
6500 |
|
| 6501 |
// Some Thumb instructions have two operand forms that are not |
6501 |
// Some Thumb instructions have two operand forms that are not |
| 6502 |
// available as three operand, convert to two operand form if possible. |
6502 |
// available as three operand, convert to two operand form if possible. |
| 6503 |
// |
6503 |
// |
| 6504 |
// FIXME: We would really like to be able to tablegen'erate this. |
6504 |
// FIXME: We would really like to be able to tablegen'erate this. |
| 6505 |
void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic, |
6505 |
void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic, |
| 6506 |
bool CarrySetting, |
6506 |
bool CarrySetting, |
| 6507 |
OperandVector &Operands) { |
6507 |
OperandVector &Operands) { |
| 6508 |
if (Operands.size() != 6) |
6508 |
if (Operands.size() != 6) |
| 6509 |
return; |
6509 |
return; |
| 6510 |
|
6510 |
|
| 6511 |
const auto &Op3 = static_cast(*Operands[3]); |
6511 |
const auto &Op3 = static_cast(*Operands[3]); |
| 6512 |
auto &Op4 = static_cast(*Operands[4]); |
6512 |
auto &Op4 = static_cast(*Operands[4]); |
| 6513 |
if (!Op3.isReg() || !Op4.isReg()) |
6513 |
if (!Op3.isReg() || !Op4.isReg()) |
| 6514 |
return; |
6514 |
return; |
| 6515 |
|
6515 |
|
| 6516 |
auto Op3Reg = Op3.getReg(); |
6516 |
auto Op3Reg = Op3.getReg(); |
| 6517 |
auto Op4Reg = Op4.getReg(); |
6517 |
auto Op4Reg = Op4.getReg(); |
| 6518 |
|
6518 |
|
| 6519 |
// For most Thumb2 cases we just generate the 3 operand form and reduce |
6519 |
// For most Thumb2 cases we just generate the 3 operand form and reduce |
| 6520 |
// it in processInstruction(), but the 3 operand form of ADD (t2ADDrr) |
6520 |
// it in processInstruction(), but the 3 operand form of ADD (t2ADDrr) |
| 6521 |
// won't accept SP or PC so we do the transformation here taking care |
6521 |
// won't accept SP or PC so we do the transformation here taking care |
| 6522 |
// with immediate range in the 'add sp, sp #imm' case. |
6522 |
// with immediate range in the 'add sp, sp #imm' case. |
| 6523 |
auto &Op5 = static_cast(*Operands[5]); |
6523 |
auto &Op5 = static_cast(*Operands[5]); |
| 6524 |
if (isThumbTwo()) { |
6524 |
if (isThumbTwo()) { |
| 6525 |
if (Mnemonic != "add") |
6525 |
if (Mnemonic != "add") |
| 6526 |
return; |
6526 |
return; |
| 6527 |
bool TryTransform = Op3Reg == ARM::PC || Op4Reg == ARM::PC || |
6527 |
bool TryTransform = Op3Reg == ARM::PC || Op4Reg == ARM::PC || |
| 6528 |
(Op5.isReg() && Op5.getReg() == ARM::PC); |
6528 |
(Op5.isReg() && Op5.getReg() == ARM::PC); |
| 6529 |
if (!TryTransform) { |
6529 |
if (!TryTransform) { |
| 6530 |
TryTransform = (Op3Reg == ARM::SP || Op4Reg == ARM::SP || |
6530 |
TryTransform = (Op3Reg == ARM::SP || Op4Reg == ARM::SP || |
| 6531 |
(Op5.isReg() && Op5.getReg() == ARM::SP)) && |
6531 |
(Op5.isReg() && Op5.getReg() == ARM::SP)) && |
| 6532 |
!(Op3Reg == ARM::SP && Op4Reg == ARM::SP && |
6532 |
!(Op3Reg == ARM::SP && Op4Reg == ARM::SP && |
| 6533 |
Op5.isImm() && !Op5.isImm0_508s4()); |
6533 |
Op5.isImm() && !Op5.isImm0_508s4()); |
| 6534 |
} |
6534 |
} |
| 6535 |
if (!TryTransform) |
6535 |
if (!TryTransform) |
| 6536 |
return; |
6536 |
return; |
| 6537 |
} else if (!isThumbOne()) |
6537 |
} else if (!isThumbOne()) |
| 6538 |
return; |
6538 |
return; |
| 6539 |
|
6539 |
|
| 6540 |
if (!(Mnemonic == "add" || Mnemonic == "sub" || Mnemonic == "and" || |
6540 |
if (!(Mnemonic == "add" || Mnemonic == "sub" || Mnemonic == "and" || |
| 6541 |
Mnemonic == "eor" || Mnemonic == "lsl" || Mnemonic == "lsr" || |
6541 |
Mnemonic == "eor" || Mnemonic == "lsl" || Mnemonic == "lsr" || |
| 6542 |
Mnemonic == "asr" || Mnemonic == "adc" || Mnemonic == "sbc" || |
6542 |
Mnemonic == "asr" || Mnemonic == "adc" || Mnemonic == "sbc" || |
| 6543 |
Mnemonic == "ror" || Mnemonic == "orr" || Mnemonic == "bic")) |
6543 |
Mnemonic == "ror" || Mnemonic == "orr" || Mnemonic == "bic")) |
| 6544 |
return; |
6544 |
return; |
| 6545 |
|
6545 |
|
| 6546 |
// If first 2 operands of a 3 operand instruction are the same |
6546 |
// If first 2 operands of a 3 operand instruction are the same |
| 6547 |
// then transform to 2 operand version of the same instruction |
6547 |
// then transform to 2 operand version of the same instruction |
| 6548 |
// e.g. 'adds r0, r0, #1' transforms to 'adds r0, #1' |
6548 |
// e.g. 'adds r0, r0, #1' transforms to 'adds r0, #1' |
| 6549 |
bool Transform = Op3Reg == Op4Reg; |
6549 |
bool Transform = Op3Reg == Op4Reg; |
| 6550 |
|
6550 |
|
| 6551 |
// For communtative operations, we might be able to transform if we swap |
6551 |
// For communtative operations, we might be able to transform if we swap |
| 6552 |
// Op4 and Op5. The 'ADD Rdm, SP, Rdm' form is already handled specially |
6552 |
// Op4 and Op5. The 'ADD Rdm, SP, Rdm' form is already handled specially |
| 6553 |
// as tADDrsp. |
6553 |
// as tADDrsp. |
| 6554 |
const ARMOperand *LastOp = &Op5; |
6554 |
const ARMOperand *LastOp = &Op5; |
| 6555 |
bool Swap = false; |
6555 |
bool Swap = false; |
| 6556 |
if (!Transform && Op5.isReg() && Op3Reg == Op5.getReg() && |
6556 |
if (!Transform && Op5.isReg() && Op3Reg == Op5.getReg() && |
| 6557 |
((Mnemonic == "add" && Op4Reg != ARM::SP) || |
6557 |
((Mnemonic == "add" && Op4Reg != ARM::SP) || |
| 6558 |
Mnemonic == "and" || Mnemonic == "eor" || |
6558 |
Mnemonic == "and" || Mnemonic == "eor" || |
| 6559 |
Mnemonic == "adc" || Mnemonic == "orr")) { |
6559 |
Mnemonic == "adc" || Mnemonic == "orr")) { |
| 6560 |
Swap = true; |
6560 |
Swap = true; |
| 6561 |
LastOp = &Op4; |
6561 |
LastOp = &Op4; |
| 6562 |
Transform = true; |
6562 |
Transform = true; |
| 6563 |
} |
6563 |
} |
| 6564 |
|
6564 |
|
| 6565 |
// If both registers are the same then remove one of them from |
6565 |
// If both registers are the same then remove one of them from |
| 6566 |
// the operand list, with certain exceptions. |
6566 |
// the operand list, with certain exceptions. |
| 6567 |
if (Transform) { |
6567 |
if (Transform) { |
| 6568 |
// Don't transform 'adds Rd, Rd, Rm' or 'sub{s} Rd, Rd, Rm' because the |
6568 |
// Don't transform 'adds Rd, Rd, Rm' or 'sub{s} Rd, Rd, Rm' because the |
| 6569 |
// 2 operand forms don't exist. |
6569 |
// 2 operand forms don't exist. |
| 6570 |
if (((Mnemonic == "add" && CarrySetting) || Mnemonic == "sub") && |
6570 |
if (((Mnemonic == "add" && CarrySetting) || Mnemonic == "sub") && |
| 6571 |
LastOp->isReg()) |
6571 |
LastOp->isReg()) |
| 6572 |
Transform = false; |
6572 |
Transform = false; |
| 6573 |
|
6573 |
|
| 6574 |
// Don't transform 'add/sub{s} Rd, Rd, #imm' if the immediate fits into |
6574 |
// Don't transform 'add/sub{s} Rd, Rd, #imm' if the immediate fits into |
| 6575 |
// 3-bits because the ARMARM says not to. |
6575 |
// 3-bits because the ARMARM says not to. |
| 6576 |
if ((Mnemonic == "add" || Mnemonic == "sub") && LastOp->isImm0_7()) |
6576 |
if ((Mnemonic == "add" || Mnemonic == "sub") && LastOp->isImm0_7()) |
| 6577 |
Transform = false; |
6577 |
Transform = false; |
| 6578 |
} |
6578 |
} |
| 6579 |
|
6579 |
|
| 6580 |
if (Transform) { |
6580 |
if (Transform) { |
| 6581 |
if (Swap) |
6581 |
if (Swap) |
| 6582 |
std::swap(Op4, Op5); |
6582 |
std::swap(Op4, Op5); |
| 6583 |
Operands.erase(Operands.begin() + 3); |
6583 |
Operands.erase(Operands.begin() + 3); |
| 6584 |
} |
6584 |
} |
| 6585 |
} |
6585 |
} |
| 6586 |
|
6586 |
|
| 6587 |
// this function returns true if the operand is one of the following |
6587 |
// this function returns true if the operand is one of the following |
| 6588 |
// relocations: :upper8_15:, :upper0_7:, :lower8_15: or :lower0_7: |
6588 |
// relocations: :upper8_15:, :upper0_7:, :lower8_15: or :lower0_7: |
| 6589 |
static bool isThumbI8Relocation(MCParsedAsmOperand &MCOp) { |
6589 |
static bool isThumbI8Relocation(MCParsedAsmOperand &MCOp) { |
| 6590 |
ARMOperand &Op = static_cast(MCOp); |
6590 |
ARMOperand &Op = static_cast(MCOp); |
| 6591 |
if (!Op.isImm()) |
6591 |
if (!Op.isImm()) |
| 6592 |
return false; |
6592 |
return false; |
| 6593 |
const MCConstantExpr *CE = dyn_cast(Op.getImm()); |
6593 |
const MCConstantExpr *CE = dyn_cast(Op.getImm()); |
| 6594 |
if (CE) |
6594 |
if (CE) |
| 6595 |
return false; |
6595 |
return false; |
| 6596 |
const MCExpr *E = dyn_cast(Op.getImm()); |
6596 |
const MCExpr *E = dyn_cast(Op.getImm()); |
| 6597 |
if (!E) |
6597 |
if (!E) |
| 6598 |
return false; |
6598 |
return false; |
| 6599 |
const ARMMCExpr *ARM16Expr = dyn_cast(E); |
6599 |
const ARMMCExpr *ARM16Expr = dyn_cast(E); |
| 6600 |
if (ARM16Expr && (ARM16Expr->getKind() == ARMMCExpr::VK_ARM_HI_8_15 || |
6600 |
if (ARM16Expr && (ARM16Expr->getKind() == ARMMCExpr::VK_ARM_HI_8_15 || |
| 6601 |
ARM16Expr->getKind() == ARMMCExpr::VK_ARM_HI_0_7 || |
6601 |
ARM16Expr->getKind() == ARMMCExpr::VK_ARM_HI_0_7 || |
| 6602 |
ARM16Expr->getKind() == ARMMCExpr::VK_ARM_LO_8_15 || |
6602 |
ARM16Expr->getKind() == ARMMCExpr::VK_ARM_LO_8_15 || |
| 6603 |
ARM16Expr->getKind() == ARMMCExpr::VK_ARM_LO_0_7)) |
6603 |
ARM16Expr->getKind() == ARMMCExpr::VK_ARM_LO_0_7)) |
| 6604 |
return true; |
6604 |
return true; |
| 6605 |
return false; |
6605 |
return false; |
| 6606 |
} |
6606 |
} |
| 6607 |
|
6607 |
|
| 6608 |
bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, |
6608 |
bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, |
| 6609 |
OperandVector &Operands) { |
6609 |
OperandVector &Operands) { |
| 6610 |
// FIXME: This is all horribly hacky. We really need a better way to deal |
6610 |
// FIXME: This is all horribly hacky. We really need a better way to deal |
| 6611 |
// with optional operands like this in the matcher table. |
6611 |
// with optional operands like this in the matcher table. |
| 6612 |
|
6612 |
|
| 6613 |
// The 'mov' mnemonic is special. One variant has a cc_out operand, while |
6613 |
// The 'mov' mnemonic is special. One variant has a cc_out operand, while |
| 6614 |
// another does not. Specifically, the MOVW instruction does not. So we |
6614 |
// another does not. Specifically, the MOVW instruction does not. So we |
| 6615 |
// special case it here and remove the defaulted (non-setting) cc_out |
6615 |
// special case it here and remove the defaulted (non-setting) cc_out |
| 6616 |
// operand if that's the instruction we're trying to match. |
6616 |
// operand if that's the instruction we're trying to match. |
| 6617 |
// |
6617 |
// |
| 6618 |
// We do this as post-processing of the explicit operands rather than just |
6618 |
// We do this as post-processing of the explicit operands rather than just |
| 6619 |
// conditionally adding the cc_out in the first place because we need |
6619 |
// conditionally adding the cc_out in the first place because we need |
| 6620 |
// to check the type of the parsed immediate operand. |
6620 |
// to check the type of the parsed immediate operand. |
| 6621 |
if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() && |
6621 |
if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() && |
| 6622 |
!static_cast(*Operands[4]).isModImm() && |
6622 |
!static_cast(*Operands[4]).isModImm() && |
| 6623 |
static_cast(*Operands[4]).isImm0_65535Expr() && |
6623 |
static_cast(*Operands[4]).isImm0_65535Expr() && |
| 6624 |
static_cast(*Operands[1]).getReg() == 0) |
6624 |
static_cast(*Operands[1]).getReg() == 0) |
| 6625 |
return true; |
6625 |
return true; |
| 6626 |
|
6626 |
|
| 6627 |
if (Mnemonic == "movs" && Operands.size() > 3 && isThumb() && |
6627 |
if (Mnemonic == "movs" && Operands.size() > 3 && isThumb() && |
| 6628 |
isThumbI8Relocation(*Operands[3])) |
6628 |
isThumbI8Relocation(*Operands[3])) |
| 6629 |
return true; |
6629 |
return true; |
| 6630 |
|
6630 |
|
| 6631 |
// Register-register 'add' for thumb does not have a cc_out operand |
6631 |
// Register-register 'add' for thumb does not have a cc_out operand |
| 6632 |
// when there are only two register operands. |
6632 |
// when there are only two register operands. |
| 6633 |
if (isThumb() && Mnemonic == "add" && Operands.size() == 5 && |
6633 |
if (isThumb() && Mnemonic == "add" && Operands.size() == 5 && |
| 6634 |
static_cast(*Operands[3]).isReg() && |
6634 |
static_cast(*Operands[3]).isReg() && |
| 6635 |
static_cast(*Operands[4]).isReg() && |
6635 |
static_cast(*Operands[4]).isReg() && |
| 6636 |
static_cast(*Operands[1]).getReg() == 0) |
6636 |
static_cast(*Operands[1]).getReg() == 0) |
| 6637 |
return true; |
6637 |
return true; |
| 6638 |
// Register-register 'add' for thumb does not have a cc_out operand |
6638 |
// Register-register 'add' for thumb does not have a cc_out operand |
| 6639 |
// when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do |
6639 |
// when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do |
| 6640 |
// have to check the immediate range here since Thumb2 has a variant |
6640 |
// have to check the immediate range here since Thumb2 has a variant |
| 6641 |
// that can handle a different range and has a cc_out operand. |
6641 |
// that can handle a different range and has a cc_out operand. |
| 6642 |
if (((isThumb() && Mnemonic == "add") || |
6642 |
if (((isThumb() && Mnemonic == "add") || |
| 6643 |
(isThumbTwo() && Mnemonic == "sub")) && |
6643 |
(isThumbTwo() && Mnemonic == "sub")) && |
| 6644 |
Operands.size() == 6 && static_cast(*Operands[3]).isReg() && |
6644 |
Operands.size() == 6 && static_cast(*Operands[3]).isReg() && |
| 6645 |
static_cast(*Operands[4]).isReg() && |
6645 |
static_cast(*Operands[4]).isReg() && |
| 6646 |
static_cast(*Operands[4]).getReg() == ARM::SP && |
6646 |
static_cast(*Operands[4]).getReg() == ARM::SP && |
| 6647 |
static_cast(*Operands[1]).getReg() == 0 && |
6647 |
static_cast(*Operands[1]).getReg() == 0 && |
| 6648 |
((Mnemonic == "add" && static_cast(*Operands[5]).isReg()) || |
6648 |
((Mnemonic == "add" && static_cast(*Operands[5]).isReg()) || |
| 6649 |
static_cast(*Operands[5]).isImm0_1020s4())) |
6649 |
static_cast(*Operands[5]).isImm0_1020s4())) |
| 6650 |
return true; |
6650 |
return true; |
| 6651 |
// For Thumb2, add/sub immediate does not have a cc_out operand for the |
6651 |
// For Thumb2, add/sub immediate does not have a cc_out operand for the |
| 6652 |
// imm0_4095 variant. That's the least-preferred variant when |
6652 |
// imm0_4095 variant. That's the least-preferred variant when |
| 6653 |
// selecting via the generic "add" mnemonic, so to know that we |
6653 |
// selecting via the generic "add" mnemonic, so to know that we |
| 6654 |
// should remove the cc_out operand, we have to explicitly check that |
6654 |
// should remove the cc_out operand, we have to explicitly check that |
| 6655 |
// it's not one of the other variants. Ugh. |
6655 |
// it's not one of the other variants. Ugh. |
| 6656 |
if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") && |
6656 |
if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") && |
| 6657 |
Operands.size() == 6 && static_cast(*Operands[3]).isReg() && |
6657 |
Operands.size() == 6 && static_cast(*Operands[3]).isReg() && |
| 6658 |
static_cast(*Operands[4]).isReg() && |
6658 |
static_cast(*Operands[4]).isReg() && |
| 6659 |
static_cast(*Operands[5]).isImm()) { |
6659 |
static_cast(*Operands[5]).isImm()) { |
| 6660 |
// Nest conditions rather than one big 'if' statement for readability. |
6660 |
// Nest conditions rather than one big 'if' statement for readability. |
| 6661 |
// |
6661 |
// |
| 6662 |
// If both registers are low, we're in an IT block, and the immediate is |
6662 |
// If both registers are low, we're in an IT block, and the immediate is |
| 6663 |
// in range, we should use encoding T1 instead, which has a cc_out. |
6663 |
// in range, we should use encoding T1 instead, which has a cc_out. |
| 6664 |
if (inITBlock() && |
6664 |
if (inITBlock() && |
| 6665 |
isARMLowRegister(static_cast(*Operands[3]).getReg()) && |
6665 |
isARMLowRegister(static_cast(*Operands[3]).getReg()) && |
| 6666 |
isARMLowRegister(static_cast(*Operands[4]).getReg()) && |
6666 |
isARMLowRegister(static_cast(*Operands[4]).getReg()) && |
| 6667 |
static_cast(*Operands[5]).isImm0_7()) |
6667 |
static_cast(*Operands[5]).isImm0_7()) |
| 6668 |
return false; |
6668 |
return false; |
| 6669 |
// Check against T3. If the second register is the PC, this is an |
6669 |
// Check against T3. If the second register is the PC, this is an |
| 6670 |
// alternate form of ADR, which uses encoding T4, so check for that too. |
6670 |
// alternate form of ADR, which uses encoding T4, so check for that too. |
| 6671 |
if (static_cast(*Operands[4]).getReg() != ARM::PC && |
6671 |
if (static_cast(*Operands[4]).getReg() != ARM::PC && |
| 6672 |
(static_cast(*Operands[5]).isT2SOImm() || |
6672 |
(static_cast(*Operands[5]).isT2SOImm() || |
| 6673 |
static_cast(*Operands[5]).isT2SOImmNeg())) |
6673 |
static_cast(*Operands[5]).isT2SOImmNeg())) |
| 6674 |
return false; |
6674 |
return false; |
| 6675 |
|
6675 |
|
| 6676 |
// Otherwise, we use encoding T4, which does not have a cc_out |
6676 |
// Otherwise, we use encoding T4, which does not have a cc_out |
| 6677 |
// operand. |
6677 |
// operand. |
| 6678 |
return true; |
6678 |
return true; |
| 6679 |
} |
6679 |
} |
| 6680 |
|
6680 |
|
| 6681 |
// The thumb2 multiply instruction doesn't have a CCOut register, so |
6681 |
// The thumb2 multiply instruction doesn't have a CCOut register, so |
| 6682 |
// if we have a "mul" mnemonic in Thumb mode, check if we'll be able to |
6682 |
// if we have a "mul" mnemonic in Thumb mode, check if we'll be able to |
| 6683 |
// use the 16-bit encoding or not. |
6683 |
// use the 16-bit encoding or not. |
| 6684 |
if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 && |
6684 |
if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 && |
| 6685 |
static_cast(*Operands[1]).getReg() == 0 && |
6685 |
static_cast(*Operands[1]).getReg() == 0 && |
| 6686 |
static_cast(*Operands[3]).isReg() && |
6686 |
static_cast(*Operands[3]).isReg() && |
| 6687 |
static_cast(*Operands[4]).isReg() && |
6687 |
static_cast(*Operands[4]).isReg() && |
| 6688 |
static_cast(*Operands[5]).isReg() && |
6688 |
static_cast(*Operands[5]).isReg() && |
| 6689 |
// If the registers aren't low regs, the destination reg isn't the |
6689 |
// If the registers aren't low regs, the destination reg isn't the |
| 6690 |
// same as one of the source regs, or the cc_out operand is zero |
6690 |
// same as one of the source regs, or the cc_out operand is zero |
| 6691 |
// outside of an IT block, we have to use the 32-bit encoding, so |
6691 |
// outside of an IT block, we have to use the 32-bit encoding, so |
| 6692 |
// remove the cc_out operand. |
6692 |
// remove the cc_out operand. |
| 6693 |
(!isARMLowRegister(static_cast(*Operands[3]).getReg()) || |
6693 |
(!isARMLowRegister(static_cast(*Operands[3]).getReg()) || |
| 6694 |
!isARMLowRegister(static_cast(*Operands[4]).getReg()) || |
6694 |
!isARMLowRegister(static_cast(*Operands[4]).getReg()) || |
| 6695 |
!isARMLowRegister(static_cast(*Operands[5]).getReg()) || |
6695 |
!isARMLowRegister(static_cast(*Operands[5]).getReg()) || |
| 6696 |
!inITBlock() || (static_cast(*Operands[3]).getReg() != |
6696 |
!inITBlock() || (static_cast(*Operands[3]).getReg() != |
| 6697 |
static_cast(*Operands[5]).getReg() && |
6697 |
static_cast(*Operands[5]).getReg() && |
| 6698 |
static_cast(*Operands[3]).getReg() != |
6698 |
static_cast(*Operands[3]).getReg() != |
| 6699 |
static_cast(*Operands[4]).getReg()))) |
6699 |
static_cast(*Operands[4]).getReg()))) |
| 6700 |
return true; |
6700 |
return true; |
| 6701 |
|
6701 |
|
| 6702 |
// Also check the 'mul' syntax variant that doesn't specify an explicit |
6702 |
// Also check the 'mul' syntax variant that doesn't specify an explicit |
| 6703 |
// destination register. |
6703 |
// destination register. |
| 6704 |
if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 && |
6704 |
if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 && |
| 6705 |
static_cast(*Operands[1]).getReg() == 0 && |
6705 |
static_cast(*Operands[1]).getReg() == 0 && |
| 6706 |
static_cast(*Operands[3]).isReg() && |
6706 |
static_cast(*Operands[3]).isReg() && |
| 6707 |
static_cast(*Operands[4]).isReg() && |
6707 |
static_cast(*Operands[4]).isReg() && |
| 6708 |
// If the registers aren't low regs or the cc_out operand is zero |
6708 |
// If the registers aren't low regs or the cc_out operand is zero |
| 6709 |
// outside of an IT block, we have to use the 32-bit encoding, so |
6709 |
// outside of an IT block, we have to use the 32-bit encoding, so |
| 6710 |
// remove the cc_out operand. |
6710 |
// remove the cc_out operand. |
| 6711 |
(!isARMLowRegister(static_cast(*Operands[3]).getReg()) || |
6711 |
(!isARMLowRegister(static_cast(*Operands[3]).getReg()) || |
| 6712 |
!isARMLowRegister(static_cast(*Operands[4]).getReg()) || |
6712 |
!isARMLowRegister(static_cast(*Operands[4]).getReg()) || |
| 6713 |
!inITBlock())) |
6713 |
!inITBlock())) |
| 6714 |
return true; |
6714 |
return true; |
| 6715 |
|
6715 |
|
| 6716 |
// Register-register 'add/sub' for thumb does not have a cc_out operand |
6716 |
// Register-register 'add/sub' for thumb does not have a cc_out operand |
| 6717 |
// when it's an ADD/SUB SP, #imm. Be lenient on count since there's also |
6717 |
// when it's an ADD/SUB SP, #imm. Be lenient on count since there's also |
| 6718 |
// the "add/sub SP, SP, #imm" version. If the follow-up operands aren't |
6718 |
// the "add/sub SP, SP, #imm" version. If the follow-up operands aren't |
| 6719 |
// right, this will result in better diagnostics (which operand is off) |
6719 |
// right, this will result in better diagnostics (which operand is off) |
| 6720 |
// anyway. |
6720 |
// anyway. |
| 6721 |
if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") && |
6721 |
if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") && |
| 6722 |
(Operands.size() == 5 || Operands.size() == 6) && |
6722 |
(Operands.size() == 5 || Operands.size() == 6) && |
| 6723 |
static_cast(*Operands[3]).isReg() && |
6723 |
static_cast(*Operands[3]).isReg() && |
| 6724 |
static_cast(*Operands[3]).getReg() == ARM::SP && |
6724 |
static_cast(*Operands[3]).getReg() == ARM::SP && |
| 6725 |
static_cast(*Operands[1]).getReg() == 0 && |
6725 |
static_cast(*Operands[1]).getReg() == 0 && |
| 6726 |
(static_cast(*Operands[4]).isImm() || |
6726 |
(static_cast(*Operands[4]).isImm() || |
| 6727 |
(Operands.size() == 6 && |
6727 |
(Operands.size() == 6 && |
| 6728 |
static_cast(*Operands[5]).isImm()))) { |
6728 |
static_cast(*Operands[5]).isImm()))) { |
| 6729 |
// Thumb2 (add|sub){s}{p}.w GPRnopc, sp, #{T2SOImm} has cc_out |
6729 |
// Thumb2 (add|sub){s}{p}.w GPRnopc, sp, #{T2SOImm} has cc_out |
| 6730 |
return (!(isThumbTwo() && |
6730 |
return (!(isThumbTwo() && |
| 6731 |
(static_cast(*Operands[4]).isT2SOImm() || |
6731 |
(static_cast(*Operands[4]).isT2SOImm() || |
| 6732 |
static_cast(*Operands[4]).isT2SOImmNeg()))); |
6732 |
static_cast(*Operands[4]).isT2SOImmNeg()))); |
| 6733 |
} |
6733 |
} |
| 6734 |
// Fixme: Should join all the thumb+thumb2 (add|sub) in a single if case |
6734 |
// Fixme: Should join all the thumb+thumb2 (add|sub) in a single if case |
| 6735 |
// Thumb2 ADD r0, #4095 -> ADDW r0, r0, #4095 (T4) |
6735 |
// Thumb2 ADD r0, #4095 -> ADDW r0, r0, #4095 (T4) |
| 6736 |
// Thumb2 SUB r0, #4095 -> SUBW r0, r0, #4095 |
6736 |
// Thumb2 SUB r0, #4095 -> SUBW r0, r0, #4095 |
| 6737 |
if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") && |
6737 |
if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") && |
| 6738 |
(Operands.size() == 5) && |
6738 |
(Operands.size() == 5) && |
| 6739 |
static_cast(*Operands[3]).isReg() && |
6739 |
static_cast(*Operands[3]).isReg() && |
| 6740 |
static_cast(*Operands[3]).getReg() != ARM::SP && |
6740 |
static_cast(*Operands[3]).getReg() != ARM::SP && |
| 6741 |
static_cast(*Operands[3]).getReg() != ARM::PC && |
6741 |
static_cast(*Operands[3]).getReg() != ARM::PC && |
| 6742 |
static_cast(*Operands[1]).getReg() == 0 && |
6742 |
static_cast(*Operands[1]).getReg() == 0 && |
| 6743 |
static_cast(*Operands[4]).isImm()) { |
6743 |
static_cast(*Operands[4]).isImm()) { |
| 6744 |
const ARMOperand &IMM = static_cast(*Operands[4]); |
6744 |
const ARMOperand &IMM = static_cast(*Operands[4]); |
| 6745 |
if (IMM.isT2SOImm() || IMM.isT2SOImmNeg()) |
6745 |
if (IMM.isT2SOImm() || IMM.isT2SOImmNeg()) |
| 6746 |
return false; // add.w / sub.w |
6746 |
return false; // add.w / sub.w |
| 6747 |
if (const MCConstantExpr *CE = dyn_cast(IMM.getImm())) { |
6747 |
if (const MCConstantExpr *CE = dyn_cast(IMM.getImm())) { |
| 6748 |
const int64_t Value = CE->getValue(); |
6748 |
const int64_t Value = CE->getValue(); |
| 6749 |
// Thumb1 imm8 sub / add |
6749 |
// Thumb1 imm8 sub / add |
| 6750 |
if ((Value < ((1 << 7) - 1) << 2) && inITBlock() && (!(Value & 3)) && |
6750 |
if ((Value < ((1 << 7) - 1) << 2) && inITBlock() && (!(Value & 3)) && |
| 6751 |
isARMLowRegister(static_cast(*Operands[3]).getReg())) |
6751 |
isARMLowRegister(static_cast(*Operands[3]).getReg())) |
| 6752 |
return false; |
6752 |
return false; |
| 6753 |
return true; // Thumb2 T4 addw / subw |
6753 |
return true; // Thumb2 T4 addw / subw |
| 6754 |
} |
6754 |
} |
| 6755 |
} |
6755 |
} |
| 6756 |
return false; |
6756 |
return false; |
| 6757 |
} |
6757 |
} |
| 6758 |
|
6758 |
|
| 6759 |
bool ARMAsmParser::shouldOmitPredicateOperand(StringRef Mnemonic, |
6759 |
bool ARMAsmParser::shouldOmitPredicateOperand(StringRef Mnemonic, |
| 6760 |
OperandVector &Operands) { |
6760 |
OperandVector &Operands) { |
| 6761 |
// VRINT{Z, X} have a predicate operand in VFP, but not in NEON |
6761 |
// VRINT{Z, X} have a predicate operand in VFP, but not in NEON |
| 6762 |
unsigned RegIdx = 3; |
6762 |
unsigned RegIdx = 3; |
| 6763 |
if ((((Mnemonic == "vrintz" || Mnemonic == "vrintx") && !hasMVE()) || |
6763 |
if ((((Mnemonic == "vrintz" || Mnemonic == "vrintx") && !hasMVE()) || |
| 6764 |
Mnemonic == "vrintr") && |
6764 |
Mnemonic == "vrintr") && |
| 6765 |
(static_cast(*Operands[2]).getToken() == ".f32" || |
6765 |
(static_cast(*Operands[2]).getToken() == ".f32" || |
| 6766 |
static_cast(*Operands[2]).getToken() == ".f16")) { |
6766 |
static_cast(*Operands[2]).getToken() == ".f16")) { |
| 6767 |
if (static_cast(*Operands[3]).isToken() && |
6767 |
if (static_cast(*Operands[3]).isToken() && |
| 6768 |
(static_cast(*Operands[3]).getToken() == ".f32" || |
6768 |
(static_cast(*Operands[3]).getToken() == ".f32" || |
| 6769 |
static_cast(*Operands[3]).getToken() == ".f16")) |
6769 |
static_cast(*Operands[3]).getToken() == ".f16")) |
| 6770 |
RegIdx = 4; |
6770 |
RegIdx = 4; |
| 6771 |
|
6771 |
|
| 6772 |
if (static_cast(*Operands[RegIdx]).isReg() && |
6772 |
if (static_cast(*Operands[RegIdx]).isReg() && |
| 6773 |
(ARMMCRegisterClasses[ARM::DPRRegClassID].contains( |
6773 |
(ARMMCRegisterClasses[ARM::DPRRegClassID].contains( |
| 6774 |
static_cast(*Operands[RegIdx]).getReg()) || |
6774 |
static_cast(*Operands[RegIdx]).getReg()) || |
| 6775 |
ARMMCRegisterClasses[ARM::QPRRegClassID].contains( |
6775 |
ARMMCRegisterClasses[ARM::QPRRegClassID].contains( |
| 6776 |
static_cast(*Operands[RegIdx]).getReg()))) |
6776 |
static_cast(*Operands[RegIdx]).getReg()))) |
| 6777 |
return true; |
6777 |
return true; |
| 6778 |
} |
6778 |
} |
| 6779 |
return false; |
6779 |
return false; |
| 6780 |
} |
6780 |
} |
| 6781 |
|
6781 |
|
| 6782 |
bool ARMAsmParser::shouldOmitVectorPredicateOperand(StringRef Mnemonic, |
6782 |
bool ARMAsmParser::shouldOmitVectorPredicateOperand(StringRef Mnemonic, |
| 6783 |
OperandVector &Operands) { |
6783 |
OperandVector &Operands) { |
| 6784 |
if (!hasMVE() || Operands.size() < 3) |
6784 |
if (!hasMVE() || Operands.size() < 3) |
| 6785 |
return true; |
6785 |
return true; |
| 6786 |
|
6786 |
|
| 6787 |
if (Mnemonic.startswith("vld2") || Mnemonic.startswith("vld4") || |
6787 |
if (Mnemonic.startswith("vld2") || Mnemonic.startswith("vld4") || |
| 6788 |
Mnemonic.startswith("vst2") || Mnemonic.startswith("vst4")) |
6788 |
Mnemonic.startswith("vst2") || Mnemonic.startswith("vst4")) |
| 6789 |
return true; |
6789 |
return true; |
| 6790 |
|
6790 |
|
| 6791 |
if (Mnemonic.startswith("vctp") || Mnemonic.startswith("vpnot")) |
6791 |
if (Mnemonic.startswith("vctp") || Mnemonic.startswith("vpnot")) |
| 6792 |
return false; |
6792 |
return false; |
| 6793 |
|
6793 |
|
| 6794 |
if (Mnemonic.startswith("vmov") && |
6794 |
if (Mnemonic.startswith("vmov") && |
| 6795 |
!(Mnemonic.startswith("vmovl") || Mnemonic.startswith("vmovn") || |
6795 |
!(Mnemonic.startswith("vmovl") || Mnemonic.startswith("vmovn") || |
| 6796 |
Mnemonic.startswith("vmovx"))) { |
6796 |
Mnemonic.startswith("vmovx"))) { |
| 6797 |
for (auto &Operand : Operands) { |
6797 |
for (auto &Operand : Operands) { |
| 6798 |
if (static_cast(*Operand).isVectorIndex() || |
6798 |
if (static_cast(*Operand).isVectorIndex() || |
| 6799 |
((*Operand).isReg() && |
6799 |
((*Operand).isReg() && |
| 6800 |
(ARMMCRegisterClasses[ARM::SPRRegClassID].contains( |
6800 |
(ARMMCRegisterClasses[ARM::SPRRegClassID].contains( |
| 6801 |
(*Operand).getReg()) || |
6801 |
(*Operand).getReg()) || |
| 6802 |
ARMMCRegisterClasses[ARM::DPRRegClassID].contains( |
6802 |
ARMMCRegisterClasses[ARM::DPRRegClassID].contains( |
| 6803 |
(*Operand).getReg())))) { |
6803 |
(*Operand).getReg())))) { |
| 6804 |
return true; |
6804 |
return true; |
| 6805 |
} |
6805 |
} |
| 6806 |
} |
6806 |
} |
| 6807 |
return false; |
6807 |
return false; |
| 6808 |
} else { |
6808 |
} else { |
| 6809 |
for (auto &Operand : Operands) { |
6809 |
for (auto &Operand : Operands) { |
| 6810 |
// We check the larger class QPR instead of just the legal class |
6810 |
// We check the larger class QPR instead of just the legal class |
| 6811 |
// MQPR, to more accurately report errors when using Q registers |
6811 |
// MQPR, to more accurately report errors when using Q registers |
| 6812 |
// outside of the allowed range. |
6812 |
// outside of the allowed range. |
| 6813 |
if (static_cast(*Operand).isVectorIndex() || |
6813 |
if (static_cast(*Operand).isVectorIndex() || |
| 6814 |
(Operand->isReg() && |
6814 |
(Operand->isReg() && |
| 6815 |
(ARMMCRegisterClasses[ARM::QPRRegClassID].contains( |
6815 |
(ARMMCRegisterClasses[ARM::QPRRegClassID].contains( |
| 6816 |
Operand->getReg())))) |
6816 |
Operand->getReg())))) |
| 6817 |
return false; |
6817 |
return false; |
| 6818 |
} |
6818 |
} |
| 6819 |
return true; |
6819 |
return true; |
| 6820 |
} |
6820 |
} |
| 6821 |
} |
6821 |
} |
| 6822 |
|
6822 |
|
| 6823 |
static bool isDataTypeToken(StringRef Tok) { |
6823 |
static bool isDataTypeToken(StringRef Tok) { |
| 6824 |
return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" || |
6824 |
return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" || |
| 6825 |
Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" || |
6825 |
Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" || |
| 6826 |
Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" || |
6826 |
Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" || |
| 6827 |
Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" || |
6827 |
Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" || |
| 6828 |
Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" || |
6828 |
Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" || |
| 6829 |
Tok == ".f" || Tok == ".d"; |
6829 |
Tok == ".f" || Tok == ".d"; |
| 6830 |
} |
6830 |
} |
| 6831 |
|
6831 |
|
| 6832 |
// FIXME: This bit should probably be handled via an explicit match class |
6832 |
// FIXME: This bit should probably be handled via an explicit match class |
| 6833 |
// in the .td files that matches the suffix instead of having it be |
6833 |
// in the .td files that matches the suffix instead of having it be |
| 6834 |
// a literal string token the way it is now. |
6834 |
// a literal string token the way it is now. |
| 6835 |
static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) { |
6835 |
static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) { |
| 6836 |
return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm"); |
6836 |
return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm"); |
| 6837 |
} |
6837 |
} |
| 6838 |
|
6838 |
|
| 6839 |
static void applyMnemonicAliases(StringRef &Mnemonic, |
6839 |
static void applyMnemonicAliases(StringRef &Mnemonic, |
| 6840 |
const FeatureBitset &Features, |
6840 |
const FeatureBitset &Features, |
| 6841 |
unsigned VariantID); |
6841 |
unsigned VariantID); |
| 6842 |
|
6842 |
|
| 6843 |
// The GNU assembler has aliases of ldrd and strd with the second register |
6843 |
// The GNU assembler has aliases of ldrd and strd with the second register |
| 6844 |
// omitted. We don't have a way to do that in tablegen, so fix it up here. |
6844 |
// omitted. We don't have a way to do that in tablegen, so fix it up here. |
| 6845 |
// |
6845 |
// |
| 6846 |
// We have to be careful to not emit an invalid Rt2 here, because the rest of |
6846 |
// We have to be careful to not emit an invalid Rt2 here, because the rest of |
| 6847 |
// the assembly parser could then generate confusing diagnostics refering to |
6847 |
// the assembly parser could then generate confusing diagnostics refering to |
| 6848 |
// it. If we do find anything that prevents us from doing the transformation we |
6848 |
// it. If we do find anything that prevents us from doing the transformation we |
| 6849 |
// bail out, and let the assembly parser report an error on the instruction as |
6849 |
// bail out, and let the assembly parser report an error on the instruction as |
| 6850 |
// it is written. |
6850 |
// it is written. |
| 6851 |
void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic, |
6851 |
void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic, |
| 6852 |
OperandVector &Operands) { |
6852 |
OperandVector &Operands) { |
| 6853 |
if (Mnemonic != "ldrd" && Mnemonic != "strd") |
6853 |
if (Mnemonic != "ldrd" && Mnemonic != "strd") |
| 6854 |
return; |
6854 |
return; |
| 6855 |
if (Operands.size() < 4) |
6855 |
if (Operands.size() < 4) |
| 6856 |
return; |
6856 |
return; |
| 6857 |
|
6857 |
|
| 6858 |
ARMOperand &Op2 = static_cast(*Operands[2]); |
6858 |
ARMOperand &Op2 = static_cast(*Operands[2]); |
| 6859 |
ARMOperand &Op3 = static_cast(*Operands[3]); |
6859 |
ARMOperand &Op3 = static_cast(*Operands[3]); |
| 6860 |
|
6860 |
|
| 6861 |
if (!Op2.isReg()) |
6861 |
if (!Op2.isReg()) |
| 6862 |
return; |
6862 |
return; |
| 6863 |
if (!Op3.isGPRMem()) |
6863 |
if (!Op3.isGPRMem()) |
| 6864 |
return; |
6864 |
return; |
| 6865 |
|
6865 |
|
| 6866 |
const MCRegisterClass &GPR = MRI->getRegClass(ARM::GPRRegClassID); |
6866 |
const MCRegisterClass &GPR = MRI->getRegClass(ARM::GPRRegClassID); |
| 6867 |
if (!GPR.contains(Op2.getReg())) |
6867 |
if (!GPR.contains(Op2.getReg())) |
| 6868 |
return; |
6868 |
return; |
| 6869 |
|
6869 |
|
| 6870 |
unsigned RtEncoding = MRI->getEncodingValue(Op2.getReg()); |
6870 |
unsigned RtEncoding = MRI->getEncodingValue(Op2.getReg()); |
| 6871 |
if (!isThumb() && (RtEncoding & 1)) { |
6871 |
if (!isThumb() && (RtEncoding & 1)) { |
| 6872 |
// In ARM mode, the registers must be from an aligned pair, this |
6872 |
// In ARM mode, the registers must be from an aligned pair, this |
| 6873 |
// restriction does not apply in Thumb mode. |
6873 |
// restriction does not apply in Thumb mode. |
| 6874 |
return; |
6874 |
return; |
| 6875 |
} |
6875 |
} |
| 6876 |
if (Op2.getReg() == ARM::PC) |
6876 |
if (Op2.getReg() == ARM::PC) |
| 6877 |
return; |
6877 |
return; |
| 6878 |
unsigned PairedReg = GPR.getRegister(RtEncoding + 1); |
6878 |
unsigned PairedReg = GPR.getRegister(RtEncoding + 1); |
| 6879 |
if (!PairedReg || PairedReg == ARM::PC || |
6879 |
if (!PairedReg || PairedReg == ARM::PC || |
| 6880 |
(PairedReg == ARM::SP && !hasV8Ops())) |
6880 |
(PairedReg == ARM::SP && !hasV8Ops())) |
| 6881 |
return; |
6881 |
return; |
| 6882 |
|
6882 |
|
| 6883 |
Operands.insert( |
6883 |
Operands.insert( |
| 6884 |
Operands.begin() + 3, |
6884 |
Operands.begin() + 3, |
| 6885 |
ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc())); |
6885 |
ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc())); |
| 6886 |
} |
6886 |
} |
| 6887 |
|
6887 |
|
| 6888 |
// Dual-register instruction have the following syntax: |
6888 |
// Dual-register instruction have the following syntax: |
| 6889 |
// ? , , , , ..., #imm |
6889 |
// ? , , , , ..., #imm |
| 6890 |
// This function tries to remove and replace with a pair |
6890 |
// This function tries to remove and replace with a pair |
| 6891 |
// operand. If the conversion fails an error is diagnosed, and the function |
6891 |
// operand. If the conversion fails an error is diagnosed, and the function |
| 6892 |
// returns true. |
6892 |
// returns true. |
| 6893 |
bool ARMAsmParser::CDEConvertDualRegOperand(StringRef Mnemonic, |
6893 |
bool ARMAsmParser::CDEConvertDualRegOperand(StringRef Mnemonic, |
| 6894 |
OperandVector &Operands) { |
6894 |
OperandVector &Operands) { |
| 6895 |
assert(MS.isCDEDualRegInstr(Mnemonic)); |
6895 |
assert(MS.isCDEDualRegInstr(Mnemonic)); |
| 6896 |
bool isPredicable = |
6896 |
bool isPredicable = |
| 6897 |
Mnemonic == "cx1da" || Mnemonic == "cx2da" || Mnemonic == "cx3da"; |
6897 |
Mnemonic == "cx1da" || Mnemonic == "cx2da" || Mnemonic == "cx3da"; |
| 6898 |
size_t NumPredOps = isPredicable ? 1 : 0; |
6898 |
size_t NumPredOps = isPredicable ? 1 : 0; |
| 6899 |
|
6899 |
|
| 6900 |
if (Operands.size() <= 3 + NumPredOps) |
6900 |
if (Operands.size() <= 3 + NumPredOps) |
| 6901 |
return false; |
6901 |
return false; |
| 6902 |
|
6902 |
|
| 6903 |
StringRef Op2Diag( |
6903 |
StringRef Op2Diag( |
| 6904 |
"operand must be an even-numbered register in the range [r0, r10]"); |
6904 |
"operand must be an even-numbered register in the range [r0, r10]"); |
| 6905 |
|
6905 |
|
| 6906 |
const MCParsedAsmOperand &Op2 = *Operands[2 + NumPredOps]; |
6906 |
const MCParsedAsmOperand &Op2 = *Operands[2 + NumPredOps]; |
| 6907 |
if (!Op2.isReg()) |
6907 |
if (!Op2.isReg()) |
| 6908 |
return Error(Op2.getStartLoc(), Op2Diag); |
6908 |
return Error(Op2.getStartLoc(), Op2Diag); |
| 6909 |
|
6909 |
|
| 6910 |
unsigned RNext; |
6910 |
unsigned RNext; |
| 6911 |
unsigned RPair; |
6911 |
unsigned RPair; |
| 6912 |
switch (Op2.getReg()) { |
6912 |
switch (Op2.getReg()) { |
| 6913 |
default: |
6913 |
default: |
| 6914 |
return Error(Op2.getStartLoc(), Op2Diag); |
6914 |
return Error(Op2.getStartLoc(), Op2Diag); |
| 6915 |
case ARM::R0: |
6915 |
case ARM::R0: |
| 6916 |
RNext = ARM::R1; |
6916 |
RNext = ARM::R1; |
| 6917 |
RPair = ARM::R0_R1; |
6917 |
RPair = ARM::R0_R1; |
| 6918 |
break; |
6918 |
break; |
| 6919 |
case ARM::R2: |
6919 |
case ARM::R2: |
| 6920 |
RNext = ARM::R3; |
6920 |
RNext = ARM::R3; |
| 6921 |
RPair = ARM::R2_R3; |
6921 |
RPair = ARM::R2_R3; |
| 6922 |
break; |
6922 |
break; |
| 6923 |
case ARM::R4: |
6923 |
case ARM::R4: |
| 6924 |
RNext = ARM::R5; |
6924 |
RNext = ARM::R5; |
| 6925 |
RPair = ARM::R4_R5; |
6925 |
RPair = ARM::R4_R5; |
| 6926 |
break; |
6926 |
break; |
| 6927 |
case ARM::R6: |
6927 |
case ARM::R6: |
| 6928 |
RNext = ARM::R7; |
6928 |
RNext = ARM::R7; |
| 6929 |
RPair = ARM::R6_R7; |
6929 |
RPair = ARM::R6_R7; |
| 6930 |
break; |
6930 |
break; |
| 6931 |
case ARM::R8: |
6931 |
case ARM::R8: |
| 6932 |
RNext = ARM::R9; |
6932 |
RNext = ARM::R9; |
| 6933 |
RPair = ARM::R8_R9; |
6933 |
RPair = ARM::R8_R9; |
| 6934 |
break; |
6934 |
break; |
| 6935 |
case ARM::R10: |
6935 |
case ARM::R10: |
| 6936 |
RNext = ARM::R11; |
6936 |
RNext = ARM::R11; |
| 6937 |
RPair = ARM::R10_R11; |
6937 |
RPair = ARM::R10_R11; |
| 6938 |
break; |
6938 |
break; |
| 6939 |
} |
6939 |
} |
| 6940 |
|
6940 |
|
| 6941 |
const MCParsedAsmOperand &Op3 = *Operands[3 + NumPredOps]; |
6941 |
const MCParsedAsmOperand &Op3 = *Operands[3 + NumPredOps]; |
| 6942 |
if (!Op3.isReg() || Op3.getReg() != RNext) |
6942 |
if (!Op3.isReg() || Op3.getReg() != RNext) |
| 6943 |
return Error(Op3.getStartLoc(), "operand must be a consecutive register"); |
6943 |
return Error(Op3.getStartLoc(), "operand must be a consecutive register"); |
| 6944 |
|
6944 |
|
| 6945 |
Operands.erase(Operands.begin() + 3 + NumPredOps); |
6945 |
Operands.erase(Operands.begin() + 3 + NumPredOps); |
| 6946 |
Operands[2 + NumPredOps] = |
6946 |
Operands[2 + NumPredOps] = |
| 6947 |
ARMOperand::CreateReg(RPair, Op2.getStartLoc(), Op2.getEndLoc()); |
6947 |
ARMOperand::CreateReg(RPair, Op2.getStartLoc(), Op2.getEndLoc()); |
| 6948 |
return false; |
6948 |
return false; |
| 6949 |
} |
6949 |
} |
| 6950 |
|
6950 |
|
| 6951 |
/// Parse an arm instruction mnemonic followed by its operands. |
6951 |
/// Parse an arm instruction mnemonic followed by its operands. |
| 6952 |
bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
6952 |
bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
| 6953 |
SMLoc NameLoc, OperandVector &Operands) { |
6953 |
SMLoc NameLoc, OperandVector &Operands) { |
| 6954 |
MCAsmParser &Parser = getParser(); |
6954 |
MCAsmParser &Parser = getParser(); |
| 6955 |
|
6955 |
|
| 6956 |
// Apply mnemonic aliases before doing anything else, as the destination |
6956 |
// Apply mnemonic aliases before doing anything else, as the destination |
| 6957 |
// mnemonic may include suffices and we want to handle them normally. |
6957 |
// mnemonic may include suffices and we want to handle them normally. |
| 6958 |
// The generic tblgen'erated code does this later, at the start of |
6958 |
// The generic tblgen'erated code does this later, at the start of |
| 6959 |
// MatchInstructionImpl(), but that's too late for aliases that include |
6959 |
// MatchInstructionImpl(), but that's too late for aliases that include |
| 6960 |
// any sort of suffix. |
6960 |
// any sort of suffix. |
| 6961 |
const FeatureBitset &AvailableFeatures = getAvailableFeatures(); |
6961 |
const FeatureBitset &AvailableFeatures = getAvailableFeatures(); |
| 6962 |
unsigned AssemblerDialect = getParser().getAssemblerDialect(); |
6962 |
unsigned AssemblerDialect = getParser().getAssemblerDialect(); |
| 6963 |
applyMnemonicAliases(Name, AvailableFeatures, AssemblerDialect); |
6963 |
applyMnemonicAliases(Name, AvailableFeatures, AssemblerDialect); |
| 6964 |
|
6964 |
|
| 6965 |
// First check for the ARM-specific .req directive. |
6965 |
// First check for the ARM-specific .req directive. |
| 6966 |
if (Parser.getTok().is(AsmToken::Identifier) && |
6966 |
if (Parser.getTok().is(AsmToken::Identifier) && |
| 6967 |
Parser.getTok().getIdentifier().lower() == ".req") { |
6967 |
Parser.getTok().getIdentifier().lower() == ".req") { |
| 6968 |
parseDirectiveReq(Name, NameLoc); |
6968 |
parseDirectiveReq(Name, NameLoc); |
| 6969 |
// We always return 'error' for this, as we're done with this |
6969 |
// We always return 'error' for this, as we're done with this |
| 6970 |
// statement and don't need to match the 'instruction." |
6970 |
// statement and don't need to match the 'instruction." |
| 6971 |
return true; |
6971 |
return true; |
| 6972 |
} |
6972 |
} |
| 6973 |
|
6973 |
|
| 6974 |
// Create the leading tokens for the mnemonic, split by '.' characters. |
6974 |
// Create the leading tokens for the mnemonic, split by '.' characters. |
| 6975 |
size_t Start = 0, Next = Name.find('.'); |
6975 |
size_t Start = 0, Next = Name.find('.'); |
| 6976 |
StringRef Mnemonic = Name.slice(Start, Next); |
6976 |
StringRef Mnemonic = Name.slice(Start, Next); |
| 6977 |
StringRef ExtraToken = Name.slice(Next, Name.find(' ', Next + 1)); |
6977 |
StringRef ExtraToken = Name.slice(Next, Name.find(' ', Next + 1)); |
| 6978 |
|
6978 |
|
| 6979 |
// Split out the predication code and carry setting flag from the mnemonic. |
6979 |
// Split out the predication code and carry setting flag from the mnemonic. |
| 6980 |
unsigned PredicationCode; |
6980 |
unsigned PredicationCode; |
| 6981 |
unsigned VPTPredicationCode; |
6981 |
unsigned VPTPredicationCode; |
| 6982 |
unsigned ProcessorIMod; |
6982 |
unsigned ProcessorIMod; |
| 6983 |
bool CarrySetting; |
6983 |
bool CarrySetting; |
| 6984 |
StringRef ITMask; |
6984 |
StringRef ITMask; |
| 6985 |
Mnemonic = splitMnemonic(Mnemonic, ExtraToken, PredicationCode, VPTPredicationCode, |
6985 |
Mnemonic = splitMnemonic(Mnemonic, ExtraToken, PredicationCode, VPTPredicationCode, |
| 6986 |
CarrySetting, ProcessorIMod, ITMask); |
6986 |
CarrySetting, ProcessorIMod, ITMask); |
| 6987 |
|
6987 |
|
| 6988 |
// In Thumb1, only the branch (B) instruction can be predicated. |
6988 |
// In Thumb1, only the branch (B) instruction can be predicated. |
| 6989 |
if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") { |
6989 |
if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") { |
| 6990 |
return Error(NameLoc, "conditional execution not supported in Thumb1"); |
6990 |
return Error(NameLoc, "conditional execution not supported in Thumb1"); |
| 6991 |
} |
6991 |
} |
| 6992 |
|
6992 |
|
| 6993 |
Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc)); |
6993 |
Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc)); |
| 6994 |
|
6994 |
|
| 6995 |
// Handle the mask for IT and VPT instructions. In ARMOperand and |
6995 |
// Handle the mask for IT and VPT instructions. In ARMOperand and |
| 6996 |
// MCOperand, this is stored in a format independent of the |
6996 |
// MCOperand, this is stored in a format independent of the |
| 6997 |
// condition code: the lowest set bit indicates the end of the |
6997 |
// condition code: the lowest set bit indicates the end of the |
| 6998 |
// encoding, and above that, a 1 bit indicates 'else', and an 0 |
6998 |
// encoding, and above that, a 1 bit indicates 'else', and an 0 |
| 6999 |
// indicates 'then'. E.g. |
6999 |
// indicates 'then'. E.g. |
| 7000 |
// IT -> 1000 |
7000 |
// IT -> 1000 |
| 7001 |
// ITx -> x100 (ITT -> 0100, ITE -> 1100) |
7001 |
// ITx -> x100 (ITT -> 0100, ITE -> 1100) |
| 7002 |
// ITxy -> xy10 (e.g. ITET -> 1010) |
7002 |
// ITxy -> xy10 (e.g. ITET -> 1010) |
| 7003 |
// ITxyz -> xyz1 (e.g. ITEET -> 1101) |
7003 |
// ITxyz -> xyz1 (e.g. ITEET -> 1101) |
| 7004 |
// Note: See the ARM::PredBlockMask enum in |
7004 |
// Note: See the ARM::PredBlockMask enum in |
| 7005 |
// /lib/Target/ARM/Utils/ARMBaseInfo.h |
7005 |
// /lib/Target/ARM/Utils/ARMBaseInfo.h |
| 7006 |
if (Mnemonic == "it" || Mnemonic.startswith("vpt") || |
7006 |
if (Mnemonic == "it" || Mnemonic.startswith("vpt") || |
| 7007 |
Mnemonic.startswith("vpst")) { |
7007 |
Mnemonic.startswith("vpst")) { |
| 7008 |
SMLoc Loc = Mnemonic == "it" ? SMLoc::getFromPointer(NameLoc.getPointer() + 2) : |
7008 |
SMLoc Loc = Mnemonic == "it" ? SMLoc::getFromPointer(NameLoc.getPointer() + 2) : |
| 7009 |
Mnemonic == "vpt" ? SMLoc::getFromPointer(NameLoc.getPointer() + 3) : |
7009 |
Mnemonic == "vpt" ? SMLoc::getFromPointer(NameLoc.getPointer() + 3) : |
| 7010 |
SMLoc::getFromPointer(NameLoc.getPointer() + 4); |
7010 |
SMLoc::getFromPointer(NameLoc.getPointer() + 4); |
| 7011 |
if (ITMask.size() > 3) { |
7011 |
if (ITMask.size() > 3) { |
| 7012 |
if (Mnemonic == "it") |
7012 |
if (Mnemonic == "it") |
| 7013 |
return Error(Loc, "too many conditions on IT instruction"); |
7013 |
return Error(Loc, "too many conditions on IT instruction"); |
| 7014 |
return Error(Loc, "too many conditions on VPT instruction"); |
7014 |
return Error(Loc, "too many conditions on VPT instruction"); |
| 7015 |
} |
7015 |
} |
| 7016 |
unsigned Mask = 8; |
7016 |
unsigned Mask = 8; |
| 7017 |
for (char Pos : llvm::reverse(ITMask)) { |
7017 |
for (char Pos : llvm::reverse(ITMask)) { |
| 7018 |
if (Pos != 't' && Pos != 'e') { |
7018 |
if (Pos != 't' && Pos != 'e') { |
| 7019 |
return Error(Loc, "illegal IT block condition mask '" + ITMask + "'"); |
7019 |
return Error(Loc, "illegal IT block condition mask '" + ITMask + "'"); |
| 7020 |
} |
7020 |
} |
| 7021 |
Mask >>= 1; |
7021 |
Mask >>= 1; |
| 7022 |
if (Pos == 'e') |
7022 |
if (Pos == 'e') |
| 7023 |
Mask |= 8; |
7023 |
Mask |= 8; |
| 7024 |
} |
7024 |
} |
| 7025 |
Operands.push_back(ARMOperand::CreateITMask(Mask, Loc)); |
7025 |
Operands.push_back(ARMOperand::CreateITMask(Mask, Loc)); |
| 7026 |
} |
7026 |
} |
| 7027 |
|
7027 |
|
| 7028 |
// FIXME: This is all a pretty gross hack. We should automatically handle |
7028 |
// FIXME: This is all a pretty gross hack. We should automatically handle |
| 7029 |
// optional operands like this via tblgen. |
7029 |
// optional operands like this via tblgen. |
| 7030 |
|
7030 |
|
| 7031 |
// Next, add the CCOut and ConditionCode operands, if needed. |
7031 |
// Next, add the CCOut and ConditionCode operands, if needed. |
| 7032 |
// |
7032 |
// |
| 7033 |
// For mnemonics which can ever incorporate a carry setting bit or predication |
7033 |
// For mnemonics which can ever incorporate a carry setting bit or predication |
| 7034 |
// code, our matching model involves us always generating CCOut and |
7034 |
// code, our matching model involves us always generating CCOut and |
| 7035 |
// ConditionCode operands to match the mnemonic "as written" and then we let |
7035 |
// ConditionCode operands to match the mnemonic "as written" and then we let |
| 7036 |
// the matcher deal with finding the right instruction or generating an |
7036 |
// the matcher deal with finding the right instruction or generating an |
| 7037 |
// appropriate error. |
7037 |
// appropriate error. |
| 7038 |
bool CanAcceptCarrySet, CanAcceptPredicationCode, CanAcceptVPTPredicationCode; |
7038 |
bool CanAcceptCarrySet, CanAcceptPredicationCode, CanAcceptVPTPredicationCode; |
| 7039 |
getMnemonicAcceptInfo(Mnemonic, ExtraToken, Name, CanAcceptCarrySet, |
7039 |
getMnemonicAcceptInfo(Mnemonic, ExtraToken, Name, CanAcceptCarrySet, |
| 7040 |
CanAcceptPredicationCode, CanAcceptVPTPredicationCode); |
7040 |
CanAcceptPredicationCode, CanAcceptVPTPredicationCode); |
| 7041 |
|
7041 |
|
| 7042 |
// If we had a carry-set on an instruction that can't do that, issue an |
7042 |
// If we had a carry-set on an instruction that can't do that, issue an |
| 7043 |
// error. |
7043 |
// error. |
| 7044 |
if (!CanAcceptCarrySet && CarrySetting) { |
7044 |
if (!CanAcceptCarrySet && CarrySetting) { |
| 7045 |
return Error(NameLoc, "instruction '" + Mnemonic + |
7045 |
return Error(NameLoc, "instruction '" + Mnemonic + |
| 7046 |
"' can not set flags, but 's' suffix specified"); |
7046 |
"' can not set flags, but 's' suffix specified"); |
| 7047 |
} |
7047 |
} |
| 7048 |
// If we had a predication code on an instruction that can't do that, issue an |
7048 |
// If we had a predication code on an instruction that can't do that, issue an |
| 7049 |
// error. |
7049 |
// error. |
| 7050 |
if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) { |
7050 |
if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) { |
| 7051 |
return Error(NameLoc, "instruction '" + Mnemonic + |
7051 |
return Error(NameLoc, "instruction '" + Mnemonic + |
| 7052 |
"' is not predicable, but condition code specified"); |
7052 |
"' is not predicable, but condition code specified"); |
| 7053 |
} |
7053 |
} |
| 7054 |
|
7054 |
|
| 7055 |
// If we had a VPT predication code on an instruction that can't do that, issue an |
7055 |
// If we had a VPT predication code on an instruction that can't do that, issue an |
| 7056 |
// error. |
7056 |
// error. |
| 7057 |
if (!CanAcceptVPTPredicationCode && VPTPredicationCode != ARMVCC::None) { |
7057 |
if (!CanAcceptVPTPredicationCode && VPTPredicationCode != ARMVCC::None) { |
| 7058 |
return Error(NameLoc, "instruction '" + Mnemonic + |
7058 |
return Error(NameLoc, "instruction '" + Mnemonic + |
| 7059 |
"' is not VPT predicable, but VPT code T/E is specified"); |
7059 |
"' is not VPT predicable, but VPT code T/E is specified"); |
| 7060 |
} |
7060 |
} |
| 7061 |
|
7061 |
|
| 7062 |
// Add the carry setting operand, if necessary. |
7062 |
// Add the carry setting operand, if necessary. |
| 7063 |
if (CanAcceptCarrySet) { |
7063 |
if (CanAcceptCarrySet) { |
| 7064 |
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size()); |
7064 |
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size()); |
| 7065 |
Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, |
7065 |
Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, |
| 7066 |
Loc)); |
7066 |
Loc)); |
| 7067 |
} |
7067 |
} |
| 7068 |
|
7068 |
|
| 7069 |
// Add the predication code operand, if necessary. |
7069 |
// Add the predication code operand, if necessary. |
| 7070 |
if (CanAcceptPredicationCode) { |
7070 |
if (CanAcceptPredicationCode) { |
| 7071 |
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + |
7071 |
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + |
| 7072 |
CarrySetting); |
7072 |
CarrySetting); |
| 7073 |
Operands.push_back(ARMOperand::CreateCondCode( |
7073 |
Operands.push_back(ARMOperand::CreateCondCode( |
| 7074 |
ARMCC::CondCodes(PredicationCode), Loc)); |
7074 |
ARMCC::CondCodes(PredicationCode), Loc)); |
| 7075 |
} |
7075 |
} |
| 7076 |
|
7076 |
|
| 7077 |
// Add the VPT predication code operand, if necessary. |
7077 |
// Add the VPT predication code operand, if necessary. |
| 7078 |
// FIXME: We don't add them for the instructions filtered below as these can |
7078 |
// FIXME: We don't add them for the instructions filtered below as these can |
| 7079 |
// have custom operands which need special parsing. This parsing requires |
7079 |
// have custom operands which need special parsing. This parsing requires |
| 7080 |
// the operand to be in the same place in the OperandVector as their |
7080 |
// the operand to be in the same place in the OperandVector as their |
| 7081 |
// definition in tblgen. Since these instructions may also have the |
7081 |
// definition in tblgen. Since these instructions may also have the |
| 7082 |
// scalar predication operand we do not add the vector one and leave until |
7082 |
// scalar predication operand we do not add the vector one and leave until |
| 7083 |
// now to fix it up. |
7083 |
// now to fix it up. |
| 7084 |
if (CanAcceptVPTPredicationCode && Mnemonic != "vmov" && |
7084 |
if (CanAcceptVPTPredicationCode && Mnemonic != "vmov" && |
| 7085 |
!Mnemonic.startswith("vcmp") && |
7085 |
!Mnemonic.startswith("vcmp") && |
| 7086 |
!(Mnemonic.startswith("vcvt") && Mnemonic != "vcvta" && |
7086 |
!(Mnemonic.startswith("vcvt") && Mnemonic != "vcvta" && |
| 7087 |
Mnemonic != "vcvtn" && Mnemonic != "vcvtp" && Mnemonic != "vcvtm")) { |
7087 |
Mnemonic != "vcvtn" && Mnemonic != "vcvtp" && Mnemonic != "vcvtm")) { |
| 7088 |
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + |
7088 |
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + |
| 7089 |
CarrySetting); |
7089 |
CarrySetting); |
| 7090 |
Operands.push_back(ARMOperand::CreateVPTPred( |
7090 |
Operands.push_back(ARMOperand::CreateVPTPred( |
| 7091 |
ARMVCC::VPTCodes(VPTPredicationCode), Loc)); |
7091 |
ARMVCC::VPTCodes(VPTPredicationCode), Loc)); |
| 7092 |
} |
7092 |
} |
| 7093 |
|
7093 |
|
| 7094 |
// Add the processor imod operand, if necessary. |
7094 |
// Add the processor imod operand, if necessary. |
| 7095 |
if (ProcessorIMod) { |
7095 |
if (ProcessorIMod) { |
| 7096 |
Operands.push_back(ARMOperand::CreateImm( |
7096 |
Operands.push_back(ARMOperand::CreateImm( |
| 7097 |
MCConstantExpr::create(ProcessorIMod, getContext()), |
7097 |
MCConstantExpr::create(ProcessorIMod, getContext()), |
| 7098 |
NameLoc, NameLoc)); |
7098 |
NameLoc, NameLoc)); |
| 7099 |
} else if (Mnemonic == "cps" && isMClass()) { |
7099 |
} else if (Mnemonic == "cps" && isMClass()) { |
| 7100 |
return Error(NameLoc, "instruction 'cps' requires effect for M-class"); |
7100 |
return Error(NameLoc, "instruction 'cps' requires effect for M-class"); |
| 7101 |
} |
7101 |
} |
| 7102 |
|
7102 |
|
| 7103 |
// Add the remaining tokens in the mnemonic. |
7103 |
// Add the remaining tokens in the mnemonic. |
| 7104 |
while (Next != StringRef::npos) { |
7104 |
while (Next != StringRef::npos) { |
| 7105 |
Start = Next; |
7105 |
Start = Next; |
| 7106 |
Next = Name.find('.', Start + 1); |
7106 |
Next = Name.find('.', Start + 1); |
| 7107 |
ExtraToken = Name.slice(Start, Next); |
7107 |
ExtraToken = Name.slice(Start, Next); |
| 7108 |
|
7108 |
|
| 7109 |
// Some NEON instructions have an optional datatype suffix that is |
7109 |
// Some NEON instructions have an optional datatype suffix that is |
| 7110 |
// completely ignored. Check for that. |
7110 |
// completely ignored. Check for that. |
| 7111 |
if (isDataTypeToken(ExtraToken) && |
7111 |
if (isDataTypeToken(ExtraToken) && |
| 7112 |
doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken)) |
7112 |
doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken)) |
| 7113 |
continue; |
7113 |
continue; |
| 7114 |
|
7114 |
|
| 7115 |
// For for ARM mode generate an error if the .n qualifier is used. |
7115 |
// For for ARM mode generate an error if the .n qualifier is used. |
| 7116 |
if (ExtraToken == ".n" && !isThumb()) { |
7116 |
if (ExtraToken == ".n" && !isThumb()) { |
| 7117 |
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); |
7117 |
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); |
| 7118 |
return Error(Loc, "instruction with .n (narrow) qualifier not allowed in " |
7118 |
return Error(Loc, "instruction with .n (narrow) qualifier not allowed in " |
| 7119 |
"arm mode"); |
7119 |
"arm mode"); |
| 7120 |
} |
7120 |
} |
| 7121 |
|
7121 |
|
| 7122 |
// The .n qualifier is always discarded as that is what the tables |
7122 |
// The .n qualifier is always discarded as that is what the tables |
| 7123 |
// and matcher expect. In ARM mode the .w qualifier has no effect, |
7123 |
// and matcher expect. In ARM mode the .w qualifier has no effect, |
| 7124 |
// so discard it to avoid errors that can be caused by the matcher. |
7124 |
// so discard it to avoid errors that can be caused by the matcher. |
| 7125 |
if (ExtraToken != ".n" && (isThumb() || ExtraToken != ".w")) { |
7125 |
if (ExtraToken != ".n" && (isThumb() || ExtraToken != ".w")) { |
| 7126 |
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); |
7126 |
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); |
| 7127 |
Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc)); |
7127 |
Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc)); |
| 7128 |
} |
7128 |
} |
| 7129 |
} |
7129 |
} |
| 7130 |
|
7130 |
|
| 7131 |
// Read the remaining operands. |
7131 |
// Read the remaining operands. |
| 7132 |
if (getLexer().isNot(AsmToken::EndOfStatement)) { |
7132 |
if (getLexer().isNot(AsmToken::EndOfStatement)) { |
| 7133 |
// Read the first operand. |
7133 |
// Read the first operand. |
| 7134 |
if (parseOperand(Operands, Mnemonic)) { |
7134 |
if (parseOperand(Operands, Mnemonic)) { |
| 7135 |
return true; |
7135 |
return true; |
| 7136 |
} |
7136 |
} |
| 7137 |
|
7137 |
|
| 7138 |
while (parseOptionalToken(AsmToken::Comma)) { |
7138 |
while (parseOptionalToken(AsmToken::Comma)) { |
| 7139 |
// Parse and remember the operand. |
7139 |
// Parse and remember the operand. |
| 7140 |
if (parseOperand(Operands, Mnemonic)) { |
7140 |
if (parseOperand(Operands, Mnemonic)) { |
| 7141 |
return true; |
7141 |
return true; |
| 7142 |
} |
7142 |
} |
| 7143 |
} |
7143 |
} |
| 7144 |
} |
7144 |
} |
| 7145 |
|
7145 |
|
| 7146 |
if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list")) |
7146 |
if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list")) |
| 7147 |
return true; |
7147 |
return true; |
| 7148 |
|
7148 |
|
| 7149 |
tryConvertingToTwoOperandForm(Mnemonic, CarrySetting, Operands); |
7149 |
tryConvertingToTwoOperandForm(Mnemonic, CarrySetting, Operands); |
| 7150 |
|
7150 |
|
| 7151 |
if (hasCDE() && MS.isCDEInstr(Mnemonic)) { |
7151 |
if (hasCDE() && MS.isCDEInstr(Mnemonic)) { |
| 7152 |
// Dual-register instructions use even-odd register pairs as their |
7152 |
// Dual-register instructions use even-odd register pairs as their |
| 7153 |
// destination operand, in assembly such pair is spelled as two |
7153 |
// destination operand, in assembly such pair is spelled as two |
| 7154 |
// consecutive registers, without any special syntax. ConvertDualRegOperand |
7154 |
// consecutive registers, without any special syntax. ConvertDualRegOperand |
| 7155 |
// tries to convert such operand into register pair, e.g. r2, r3 -> r2_r3. |
7155 |
// tries to convert such operand into register pair, e.g. r2, r3 -> r2_r3. |
| 7156 |
// It returns true, if an error message has been emitted. If the function |
7156 |
// It returns true, if an error message has been emitted. If the function |
| 7157 |
// returns false, the function either succeeded or an error (e.g. missing |
7157 |
// returns false, the function either succeeded or an error (e.g. missing |
| 7158 |
// operand) will be diagnosed elsewhere. |
7158 |
// operand) will be diagnosed elsewhere. |
| 7159 |
if (MS.isCDEDualRegInstr(Mnemonic)) { |
7159 |
if (MS.isCDEDualRegInstr(Mnemonic)) { |
| 7160 |
bool GotError = CDEConvertDualRegOperand(Mnemonic, Operands); |
7160 |
bool GotError = CDEConvertDualRegOperand(Mnemonic, Operands); |
| 7161 |
if (GotError) |
7161 |
if (GotError) |
| 7162 |
return GotError; |
7162 |
return GotError; |
| 7163 |
} |
7163 |
} |
| 7164 |
} |
7164 |
} |
| 7165 |
|
7165 |
|
| 7166 |
// Some instructions, mostly Thumb, have forms for the same mnemonic that |
7166 |
// Some instructions, mostly Thumb, have forms for the same mnemonic that |
| 7167 |
// do and don't have a cc_out optional-def operand. With some spot-checks |
7167 |
// do and don't have a cc_out optional-def operand. With some spot-checks |
| 7168 |
// of the operand list, we can figure out which variant we're trying to |
7168 |
// of the operand list, we can figure out which variant we're trying to |
| 7169 |
// parse and adjust accordingly before actually matching. We shouldn't ever |
7169 |
// parse and adjust accordingly before actually matching. We shouldn't ever |
| 7170 |
// try to remove a cc_out operand that was explicitly set on the |
7170 |
// try to remove a cc_out operand that was explicitly set on the |
| 7171 |
// mnemonic, of course (CarrySetting == true). Reason number #317 the |
7171 |
// mnemonic, of course (CarrySetting == true). Reason number #317 the |
| 7172 |
// table driven matcher doesn't fit well with the ARM instruction set. |
7172 |
// table driven matcher doesn't fit well with the ARM instruction set. |
| 7173 |
if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) |
7173 |
if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) |
| 7174 |
Operands.erase(Operands.begin() + 1); |
7174 |
Operands.erase(Operands.begin() + 1); |
| 7175 |
|
7175 |
|
| 7176 |
// Some instructions have the same mnemonic, but don't always |
7176 |
// Some instructions have the same mnemonic, but don't always |
| 7177 |
// have a predicate. Distinguish them here and delete the |
7177 |
// have a predicate. Distinguish them here and delete the |
| 7178 |
// appropriate predicate if needed. This could be either the scalar |
7178 |
// appropriate predicate if needed. This could be either the scalar |
| 7179 |
// predication code or the vector predication code. |
7179 |
// predication code or the vector predication code. |
| 7180 |
if (PredicationCode == ARMCC::AL && |
7180 |
if (PredicationCode == ARMCC::AL && |
| 7181 |
shouldOmitPredicateOperand(Mnemonic, Operands)) |
7181 |
shouldOmitPredicateOperand(Mnemonic, Operands)) |
| 7182 |
Operands.erase(Operands.begin() + 1); |
7182 |
Operands.erase(Operands.begin() + 1); |
| 7183 |
|
7183 |
|
| 7184 |
|
7184 |
|
| 7185 |
if (hasMVE()) { |
7185 |
if (hasMVE()) { |
| 7186 |
if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands) && |
7186 |
if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands) && |
| 7187 |
Mnemonic == "vmov" && PredicationCode == ARMCC::LT) { |
7187 |
Mnemonic == "vmov" && PredicationCode == ARMCC::LT) { |
| 7188 |
// Very nasty hack to deal with the vector predicated variant of vmovlt |
7188 |
// Very nasty hack to deal with the vector predicated variant of vmovlt |
| 7189 |
// the scalar predicated vmov with condition 'lt'. We can not tell them |
7189 |
// the scalar predicated vmov with condition 'lt'. We can not tell them |
| 7190 |
// apart until we have parsed their operands. |
7190 |
// apart until we have parsed their operands. |
| 7191 |
Operands.erase(Operands.begin() + 1); |
7191 |
Operands.erase(Operands.begin() + 1); |
| 7192 |
Operands.erase(Operands.begin()); |
7192 |
Operands.erase(Operands.begin()); |
| 7193 |
SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); |
7193 |
SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); |
| 7194 |
SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + |
7194 |
SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + |
| 7195 |
Mnemonic.size() - 1 + CarrySetting); |
7195 |
Mnemonic.size() - 1 + CarrySetting); |
| 7196 |
Operands.insert(Operands.begin(), |
7196 |
Operands.insert(Operands.begin(), |
| 7197 |
ARMOperand::CreateVPTPred(ARMVCC::None, PLoc)); |
7197 |
ARMOperand::CreateVPTPred(ARMVCC::None, PLoc)); |
| 7198 |
Operands.insert(Operands.begin(), |
7198 |
Operands.insert(Operands.begin(), |
| 7199 |
ARMOperand::CreateToken(StringRef("vmovlt"), MLoc)); |
7199 |
ARMOperand::CreateToken(StringRef("vmovlt"), MLoc)); |
| 7200 |
} else if (Mnemonic == "vcvt" && PredicationCode == ARMCC::NE && |
7200 |
} else if (Mnemonic == "vcvt" && PredicationCode == ARMCC::NE && |
| 7201 |
!shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { |
7201 |
!shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { |
| 7202 |
// Another nasty hack to deal with the ambiguity between vcvt with scalar |
7202 |
// Another nasty hack to deal with the ambiguity between vcvt with scalar |
| 7203 |
// predication 'ne' and vcvtn with vector predication 'e'. As above we |
7203 |
// predication 'ne' and vcvtn with vector predication 'e'. As above we |
| 7204 |
// can only distinguish between the two after we have parsed their |
7204 |
// can only distinguish between the two after we have parsed their |
| 7205 |
// operands. |
7205 |
// operands. |
| 7206 |
Operands.erase(Operands.begin() + 1); |
7206 |
Operands.erase(Operands.begin() + 1); |
| 7207 |
Operands.erase(Operands.begin()); |
7207 |
Operands.erase(Operands.begin()); |
| 7208 |
SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); |
7208 |
SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); |
| 7209 |
SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + |
7209 |
SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + |
| 7210 |
Mnemonic.size() - 1 + CarrySetting); |
7210 |
Mnemonic.size() - 1 + CarrySetting); |
| 7211 |
Operands.insert(Operands.begin(), |
7211 |
Operands.insert(Operands.begin(), |
| 7212 |
ARMOperand::CreateVPTPred(ARMVCC::Else, PLoc)); |
7212 |
ARMOperand::CreateVPTPred(ARMVCC::Else, PLoc)); |
| 7213 |
Operands.insert(Operands.begin(), |
7213 |
Operands.insert(Operands.begin(), |
| 7214 |
ARMOperand::CreateToken(StringRef("vcvtn"), MLoc)); |
7214 |
ARMOperand::CreateToken(StringRef("vcvtn"), MLoc)); |
| 7215 |
} else if (Mnemonic == "vmul" && PredicationCode == ARMCC::LT && |
7215 |
} else if (Mnemonic == "vmul" && PredicationCode == ARMCC::LT && |
| 7216 |
!shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { |
7216 |
!shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { |
| 7217 |
// Another hack, this time to distinguish between scalar predicated vmul |
7217 |
// Another hack, this time to distinguish between scalar predicated vmul |
| 7218 |
// with 'lt' predication code and the vector instruction vmullt with |
7218 |
// with 'lt' predication code and the vector instruction vmullt with |
| 7219 |
// vector predication code "none" |
7219 |
// vector predication code "none" |
| 7220 |
Operands.erase(Operands.begin() + 1); |
7220 |
Operands.erase(Operands.begin() + 1); |
| 7221 |
Operands.erase(Operands.begin()); |
7221 |
Operands.erase(Operands.begin()); |
| 7222 |
SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); |
7222 |
SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); |
| 7223 |
Operands.insert(Operands.begin(), |
7223 |
Operands.insert(Operands.begin(), |
| 7224 |
ARMOperand::CreateToken(StringRef("vmullt"), MLoc)); |
7224 |
ARMOperand::CreateToken(StringRef("vmullt"), MLoc)); |
| 7225 |
} |
7225 |
} |
| 7226 |
// For vmov and vcmp, as mentioned earlier, we did not add the vector |
7226 |
// For vmov and vcmp, as mentioned earlier, we did not add the vector |
| 7227 |
// predication code, since these may contain operands that require |
7227 |
// predication code, since these may contain operands that require |
| 7228 |
// special parsing. So now we have to see if they require vector |
7228 |
// special parsing. So now we have to see if they require vector |
| 7229 |
// predication and replace the scalar one with the vector predication |
7229 |
// predication and replace the scalar one with the vector predication |
| 7230 |
// operand if that is the case. |
7230 |
// operand if that is the case. |
| 7231 |
else if (Mnemonic == "vmov" || Mnemonic.startswith("vcmp") || |
7231 |
else if (Mnemonic == "vmov" || Mnemonic.startswith("vcmp") || |
| 7232 |
(Mnemonic.startswith("vcvt") && !Mnemonic.startswith("vcvta") && |
7232 |
(Mnemonic.startswith("vcvt") && !Mnemonic.startswith("vcvta") && |
| 7233 |
!Mnemonic.startswith("vcvtn") && !Mnemonic.startswith("vcvtp") && |
7233 |
!Mnemonic.startswith("vcvtn") && !Mnemonic.startswith("vcvtp") && |
| 7234 |
!Mnemonic.startswith("vcvtm"))) { |
7234 |
!Mnemonic.startswith("vcvtm"))) { |
| 7235 |
if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { |
7235 |
if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { |
| 7236 |
// We could not split the vector predicate off vcvt because it might |
7236 |
// We could not split the vector predicate off vcvt because it might |
| 7237 |
// have been the scalar vcvtt instruction. Now we know its a vector |
7237 |
// have been the scalar vcvtt instruction. Now we know its a vector |
| 7238 |
// instruction, we still need to check whether its the vector |
7238 |
// instruction, we still need to check whether its the vector |
| 7239 |
// predicated vcvt with 'Then' predication or the vector vcvtt. We can |
7239 |
// predicated vcvt with 'Then' predication or the vector vcvtt. We can |
| 7240 |
// distinguish the two based on the suffixes, if it is any of |
7240 |
// distinguish the two based on the suffixes, if it is any of |
| 7241 |
// ".f16.f32", ".f32.f16", ".f16.f64" or ".f64.f16" then it is the vcvtt. |
7241 |
// ".f16.f32", ".f32.f16", ".f16.f64" or ".f64.f16" then it is the vcvtt. |
| 7242 |
if (Mnemonic.startswith("vcvtt") && Operands.size() >= 4) { |
7242 |
if (Mnemonic.startswith("vcvtt") && Operands.size() >= 4) { |
| 7243 |
auto Sz1 = static_cast(*Operands[2]); |
7243 |
auto Sz1 = static_cast(*Operands[2]); |
| 7244 |
auto Sz2 = static_cast(*Operands[3]); |
7244 |
auto Sz2 = static_cast(*Operands[3]); |
| 7245 |
if (!(Sz1.isToken() && Sz1.getToken().startswith(".f") && |
7245 |
if (!(Sz1.isToken() && Sz1.getToken().startswith(".f") && |
| 7246 |
Sz2.isToken() && Sz2.getToken().startswith(".f"))) { |
7246 |
Sz2.isToken() && Sz2.getToken().startswith(".f"))) { |
| 7247 |
Operands.erase(Operands.begin()); |
7247 |
Operands.erase(Operands.begin()); |
| 7248 |
SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); |
7248 |
SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); |
| 7249 |
VPTPredicationCode = ARMVCC::Then; |
7249 |
VPTPredicationCode = ARMVCC::Then; |
| 7250 |
|
7250 |
|
| 7251 |
Mnemonic = Mnemonic.substr(0, 4); |
7251 |
Mnemonic = Mnemonic.substr(0, 4); |
| 7252 |
Operands.insert(Operands.begin(), |
7252 |
Operands.insert(Operands.begin(), |
| 7253 |
ARMOperand::CreateToken(Mnemonic, MLoc)); |
7253 |
ARMOperand::CreateToken(Mnemonic, MLoc)); |
| 7254 |
} |
7254 |
} |
| 7255 |
} |
7255 |
} |
| 7256 |
Operands.erase(Operands.begin() + 1); |
7256 |
Operands.erase(Operands.begin() + 1); |
| 7257 |
SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + |
7257 |
SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + |
| 7258 |
Mnemonic.size() + CarrySetting); |
7258 |
Mnemonic.size() + CarrySetting); |
| 7259 |
Operands.insert(Operands.begin() + 1, |
7259 |
Operands.insert(Operands.begin() + 1, |
| 7260 |
ARMOperand::CreateVPTPred( |
7260 |
ARMOperand::CreateVPTPred( |
| 7261 |
ARMVCC::VPTCodes(VPTPredicationCode), PLoc)); |
7261 |
ARMVCC::VPTCodes(VPTPredicationCode), PLoc)); |
| 7262 |
} |
7262 |
} |
| 7263 |
} else if (CanAcceptVPTPredicationCode) { |
7263 |
} else if (CanAcceptVPTPredicationCode) { |
| 7264 |
// For all other instructions, make sure only one of the two |
7264 |
// For all other instructions, make sure only one of the two |
| 7265 |
// predication operands is left behind, depending on whether we should |
7265 |
// predication operands is left behind, depending on whether we should |
| 7266 |
// use the vector predication. |
7266 |
// use the vector predication. |
| 7267 |
if (shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { |
7267 |
if (shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { |
| 7268 |
if (CanAcceptPredicationCode) |
7268 |
if (CanAcceptPredicationCode) |
| 7269 |
Operands.erase(Operands.begin() + 2); |
7269 |
Operands.erase(Operands.begin() + 2); |
| 7270 |
else |
7270 |
else |
| 7271 |
Operands.erase(Operands.begin() + 1); |
7271 |
Operands.erase(Operands.begin() + 1); |
| 7272 |
} else if (CanAcceptPredicationCode && PredicationCode == ARMCC::AL) { |
7272 |
} else if (CanAcceptPredicationCode && PredicationCode == ARMCC::AL) { |
| 7273 |
Operands.erase(Operands.begin() + 1); |
7273 |
Operands.erase(Operands.begin() + 1); |
| 7274 |
} |
7274 |
} |
| 7275 |
} |
7275 |
} |
| 7276 |
} |
7276 |
} |
| 7277 |
|
7277 |
|
| 7278 |
if (VPTPredicationCode != ARMVCC::None) { |
7278 |
if (VPTPredicationCode != ARMVCC::None) { |
| 7279 |
bool usedVPTPredicationCode = false; |
7279 |
bool usedVPTPredicationCode = false; |
| 7280 |
for (unsigned I = 1; I < Operands.size(); ++I) |
7280 |
for (unsigned I = 1; I < Operands.size(); ++I) |
| 7281 |
if (static_cast(*Operands[I]).isVPTPred()) |
7281 |
if (static_cast(*Operands[I]).isVPTPred()) |
| 7282 |
usedVPTPredicationCode = true; |
7282 |
usedVPTPredicationCode = true; |
| 7283 |
if (!usedVPTPredicationCode) { |
7283 |
if (!usedVPTPredicationCode) { |
| 7284 |
// If we have a VPT predication code and we haven't just turned it |
7284 |
// If we have a VPT predication code and we haven't just turned it |
| 7285 |
// into an operand, then it was a mistake for splitMnemonic to |
7285 |
// into an operand, then it was a mistake for splitMnemonic to |
| 7286 |
// separate it from the rest of the mnemonic in the first place, |
7286 |
// separate it from the rest of the mnemonic in the first place, |
| 7287 |
// and this may lead to wrong disassembly (e.g. scalar floating |
7287 |
// and this may lead to wrong disassembly (e.g. scalar floating |
| 7288 |
// point VCMPE is actually a different instruction from VCMP, so |
7288 |
// point VCMPE is actually a different instruction from VCMP, so |
| 7289 |
// we mustn't treat them the same). In that situation, glue it |
7289 |
// we mustn't treat them the same). In that situation, glue it |
| 7290 |
// back on. |
7290 |
// back on. |
| 7291 |
Mnemonic = Name.slice(0, Mnemonic.size() + 1); |
7291 |
Mnemonic = Name.slice(0, Mnemonic.size() + 1); |
| 7292 |
Operands.erase(Operands.begin()); |
7292 |
Operands.erase(Operands.begin()); |
| 7293 |
Operands.insert(Operands.begin(), |
7293 |
Operands.insert(Operands.begin(), |
| 7294 |
ARMOperand::CreateToken(Mnemonic, NameLoc)); |
7294 |
ARMOperand::CreateToken(Mnemonic, NameLoc)); |
| 7295 |
} |
7295 |
} |
| 7296 |
} |
7296 |
} |
| 7297 |
|
7297 |
|
| 7298 |
// ARM mode 'blx' need special handling, as the register operand version |
7298 |
// ARM mode 'blx' need special handling, as the register operand version |
| 7299 |
// is predicable, but the label operand version is not. So, we can't rely |
7299 |
// is predicable, but the label operand version is not. So, we can't rely |
| 7300 |
// on the Mnemonic based checking to correctly figure out when to put |
7300 |
// on the Mnemonic based checking to correctly figure out when to put |
| 7301 |
// a k_CondCode operand in the list. If we're trying to match the label |
7301 |
// a k_CondCode operand in the list. If we're trying to match the label |
| 7302 |
// version, remove the k_CondCode operand here. |
7302 |
// version, remove the k_CondCode operand here. |
| 7303 |
if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 && |
7303 |
if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 && |
| 7304 |
static_cast(*Operands[2]).isImm()) |
7304 |
static_cast(*Operands[2]).isImm()) |
| 7305 |
Operands.erase(Operands.begin() + 1); |
7305 |
Operands.erase(Operands.begin() + 1); |
| 7306 |
|
7306 |
|
| 7307 |
// Adjust operands of ldrexd/strexd to MCK_GPRPair. |
7307 |
// Adjust operands of ldrexd/strexd to MCK_GPRPair. |
| 7308 |
// ldrexd/strexd require even/odd GPR pair. To enforce this constraint, |
7308 |
// ldrexd/strexd require even/odd GPR pair. To enforce this constraint, |
| 7309 |
// a single GPRPair reg operand is used in the .td file to replace the two |
7309 |
// a single GPRPair reg operand is used in the .td file to replace the two |
| 7310 |
// GPRs. However, when parsing from asm, the two GRPs cannot be |
7310 |
// GPRs. However, when parsing from asm, the two GRPs cannot be |
| 7311 |
// automatically |
7311 |
// automatically |
| 7312 |
// expressed as a GPRPair, so we have to manually merge them. |
7312 |
// expressed as a GPRPair, so we have to manually merge them. |
| 7313 |
// FIXME: We would really like to be able to tablegen'erate this. |
7313 |
// FIXME: We would really like to be able to tablegen'erate this. |
| 7314 |
if (!isThumb() && Operands.size() > 4 && |
7314 |
if (!isThumb() && Operands.size() > 4 && |
| 7315 |
(Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" || |
7315 |
(Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" || |
| 7316 |
Mnemonic == "stlexd")) { |
7316 |
Mnemonic == "stlexd")) { |
| 7317 |
bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd"); |
7317 |
bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd"); |
| 7318 |
unsigned Idx = isLoad ? 2 : 3; |
7318 |
unsigned Idx = isLoad ? 2 : 3; |
| 7319 |
ARMOperand &Op1 = static_cast(*Operands[Idx]); |
7319 |
ARMOperand &Op1 = static_cast(*Operands[Idx]); |
| 7320 |
ARMOperand &Op2 = static_cast(*Operands[Idx + 1]); |
7320 |
ARMOperand &Op2 = static_cast(*Operands[Idx + 1]); |
| 7321 |
|
7321 |
|
| 7322 |
const MCRegisterClass &MRC = MRI->getRegClass(ARM::GPRRegClassID); |
7322 |
const MCRegisterClass &MRC = MRI->getRegClass(ARM::GPRRegClassID); |
| 7323 |
// Adjust only if Op1 and Op2 are GPRs. |
7323 |
// Adjust only if Op1 and Op2 are GPRs. |
| 7324 |
if (Op1.isReg() && Op2.isReg() && MRC.contains(Op1.getReg()) && |
7324 |
if (Op1.isReg() && Op2.isReg() && MRC.contains(Op1.getReg()) && |
| 7325 |
MRC.contains(Op2.getReg())) { |
7325 |
MRC.contains(Op2.getReg())) { |
| 7326 |
unsigned Reg1 = Op1.getReg(); |
7326 |
unsigned Reg1 = Op1.getReg(); |
| 7327 |
unsigned Reg2 = Op2.getReg(); |
7327 |
unsigned Reg2 = Op2.getReg(); |
| 7328 |
unsigned Rt = MRI->getEncodingValue(Reg1); |
7328 |
unsigned Rt = MRI->getEncodingValue(Reg1); |
| 7329 |
unsigned Rt2 = MRI->getEncodingValue(Reg2); |
7329 |
unsigned Rt2 = MRI->getEncodingValue(Reg2); |
| 7330 |
|
7330 |
|
| 7331 |
// Rt2 must be Rt + 1 and Rt must be even. |
7331 |
// Rt2 must be Rt + 1 and Rt must be even. |
| 7332 |
if (Rt + 1 != Rt2 || (Rt & 1)) { |
7332 |
if (Rt + 1 != Rt2 || (Rt & 1)) { |
| 7333 |
return Error(Op2.getStartLoc(), |
7333 |
return Error(Op2.getStartLoc(), |
| 7334 |
isLoad ? "destination operands must be sequential" |
7334 |
isLoad ? "destination operands must be sequential" |
| 7335 |
: "source operands must be sequential"); |
7335 |
: "source operands must be sequential"); |
| 7336 |
} |
7336 |
} |
| 7337 |
unsigned NewReg = MRI->getMatchingSuperReg( |
7337 |
unsigned NewReg = MRI->getMatchingSuperReg( |
| 7338 |
Reg1, ARM::gsub_0, &(MRI->getRegClass(ARM::GPRPairRegClassID))); |
7338 |
Reg1, ARM::gsub_0, &(MRI->getRegClass(ARM::GPRPairRegClassID))); |
| 7339 |
Operands[Idx] = |
7339 |
Operands[Idx] = |
| 7340 |
ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc()); |
7340 |
ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc()); |
| 7341 |
Operands.erase(Operands.begin() + Idx + 1); |
7341 |
Operands.erase(Operands.begin() + Idx + 1); |
| 7342 |
} |
7342 |
} |
| 7343 |
} |
7343 |
} |
| 7344 |
|
7344 |
|
| 7345 |
// GNU Assembler extension (compatibility). |
7345 |
// GNU Assembler extension (compatibility). |
| 7346 |
fixupGNULDRDAlias(Mnemonic, Operands); |
7346 |
fixupGNULDRDAlias(Mnemonic, Operands); |
| 7347 |
|
7347 |
|
| 7348 |
// FIXME: As said above, this is all a pretty gross hack. This instruction |
7348 |
// FIXME: As said above, this is all a pretty gross hack. This instruction |
| 7349 |
// does not fit with other "subs" and tblgen. |
7349 |
// does not fit with other "subs" and tblgen. |
| 7350 |
// Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction |
7350 |
// Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction |
| 7351 |
// so the Mnemonic is the original name "subs" and delete the predicate |
7351 |
// so the Mnemonic is the original name "subs" and delete the predicate |
| 7352 |
// operand so it will match the table entry. |
7352 |
// operand so it will match the table entry. |
| 7353 |
if (isThumbTwo() && Mnemonic == "sub" && Operands.size() == 6 && |
7353 |
if (isThumbTwo() && Mnemonic == "sub" && Operands.size() == 6 && |
| 7354 |
static_cast(*Operands[3]).isReg() && |
7354 |
static_cast(*Operands[3]).isReg() && |
| 7355 |
static_cast(*Operands[3]).getReg() == ARM::PC && |
7355 |
static_cast(*Operands[3]).getReg() == ARM::PC && |
| 7356 |
static_cast(*Operands[4]).isReg() && |
7356 |
static_cast(*Operands[4]).isReg() && |
| 7357 |
static_cast(*Operands[4]).getReg() == ARM::LR && |
7357 |
static_cast(*Operands[4]).getReg() == ARM::LR && |
| 7358 |
static_cast(*Operands[5]).isImm()) { |
7358 |
static_cast(*Operands[5]).isImm()) { |
| 7359 |
Operands.front() = ARMOperand::CreateToken(Name, NameLoc); |
7359 |
Operands.front() = ARMOperand::CreateToken(Name, NameLoc); |
| 7360 |
Operands.erase(Operands.begin() + 1); |
7360 |
Operands.erase(Operands.begin() + 1); |
| 7361 |
} |
7361 |
} |
| 7362 |
return false; |
7362 |
return false; |
| 7363 |
} |
7363 |
} |
| 7364 |
|
7364 |
|
| 7365 |
// Validate context-sensitive operand constraints. |
7365 |
// Validate context-sensitive operand constraints. |
| 7366 |
|
7366 |
|
| 7367 |
// return 'true' if register list contains non-low GPR registers, |
7367 |
// return 'true' if register list contains non-low GPR registers, |
| 7368 |
// 'false' otherwise. If Reg is in the register list or is HiReg, set |
7368 |
// 'false' otherwise. If Reg is in the register list or is HiReg, set |
| 7369 |
// 'containsReg' to true. |
7369 |
// 'containsReg' to true. |
| 7370 |
static bool checkLowRegisterList(const MCInst &Inst, unsigned OpNo, |
7370 |
static bool checkLowRegisterList(const MCInst &Inst, unsigned OpNo, |
| 7371 |
unsigned Reg, unsigned HiReg, |
7371 |
unsigned Reg, unsigned HiReg, |
| 7372 |
bool &containsReg) { |
7372 |
bool &containsReg) { |
| 7373 |
containsReg = false; |
7373 |
containsReg = false; |
| 7374 |
for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) { |
7374 |
for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) { |
| 7375 |
unsigned OpReg = Inst.getOperand(i).getReg(); |
7375 |
unsigned OpReg = Inst.getOperand(i).getReg(); |
| 7376 |
if (OpReg == Reg) |
7376 |
if (OpReg == Reg) |
| 7377 |
containsReg = true; |
7377 |
containsReg = true; |
| 7378 |
// Anything other than a low register isn't legal here. |
7378 |
// Anything other than a low register isn't legal here. |
| 7379 |
if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg)) |
7379 |
if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg)) |
| 7380 |
return true; |
7380 |
return true; |
| 7381 |
} |
7381 |
} |
| 7382 |
return false; |
7382 |
return false; |
| 7383 |
} |
7383 |
} |
| 7384 |
|
7384 |
|
| 7385 |
// Check if the specified regisgter is in the register list of the inst, |
7385 |
// Check if the specified regisgter is in the register list of the inst, |
| 7386 |
// starting at the indicated operand number. |
7386 |
// starting at the indicated operand number. |
| 7387 |
static bool listContainsReg(const MCInst &Inst, unsigned OpNo, unsigned Reg) { |
7387 |
static bool listContainsReg(const MCInst &Inst, unsigned OpNo, unsigned Reg) { |
| 7388 |
for (unsigned i = OpNo, e = Inst.getNumOperands(); i < e; ++i) { |
7388 |
for (unsigned i = OpNo, e = Inst.getNumOperands(); i < e; ++i) { |
| 7389 |
unsigned OpReg = Inst.getOperand(i).getReg(); |
7389 |
unsigned OpReg = Inst.getOperand(i).getReg(); |
| 7390 |
if (OpReg == Reg) |
7390 |
if (OpReg == Reg) |
| 7391 |
return true; |
7391 |
return true; |
| 7392 |
} |
7392 |
} |
| 7393 |
return false; |
7393 |
return false; |
| 7394 |
} |
7394 |
} |
| 7395 |
|
7395 |
|
| 7396 |
// Return true if instruction has the interesting property of being |
7396 |
// Return true if instruction has the interesting property of being |
| 7397 |
// allowed in IT blocks, but not being predicable. |
7397 |
// allowed in IT blocks, but not being predicable. |
| 7398 |
static bool instIsBreakpoint(const MCInst &Inst) { |
7398 |
static bool instIsBreakpoint(const MCInst &Inst) { |
| 7399 |
return Inst.getOpcode() == ARM::tBKPT || |
7399 |
return Inst.getOpcode() == ARM::tBKPT || |
| 7400 |
Inst.getOpcode() == ARM::BKPT || |
7400 |
Inst.getOpcode() == ARM::BKPT || |
| 7401 |
Inst.getOpcode() == ARM::tHLT || |
7401 |
Inst.getOpcode() == ARM::tHLT || |
| 7402 |
Inst.getOpcode() == ARM::HLT; |
7402 |
Inst.getOpcode() == ARM::HLT; |
| 7403 |
} |
7403 |
} |
| 7404 |
|
7404 |
|
| 7405 |
bool ARMAsmParser::validatetLDMRegList(const MCInst &Inst, |
7405 |
bool ARMAsmParser::validatetLDMRegList(const MCInst &Inst, |
| 7406 |
const OperandVector &Operands, |
7406 |
const OperandVector &Operands, |
| 7407 |
unsigned ListNo, bool IsARPop) { |
7407 |
unsigned ListNo, bool IsARPop) { |
| 7408 |
const ARMOperand &Op = static_cast(*Operands[ListNo]); |
7408 |
const ARMOperand &Op = static_cast(*Operands[ListNo]); |
| 7409 |
bool HasWritebackToken = Op.isToken() && Op.getToken() == "!"; |
7409 |
bool HasWritebackToken = Op.isToken() && Op.getToken() == "!"; |
| 7410 |
|
7410 |
|
| 7411 |
bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP); |
7411 |
bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP); |
| 7412 |
bool ListContainsLR = listContainsReg(Inst, ListNo, ARM::LR); |
7412 |
bool ListContainsLR = listContainsReg(Inst, ListNo, ARM::LR); |
| 7413 |
bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC); |
7413 |
bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC); |
| 7414 |
|
7414 |
|
| 7415 |
if (!IsARPop && ListContainsSP) |
7415 |
if (!IsARPop && ListContainsSP) |
| 7416 |
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), |
7416 |
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), |
| 7417 |
"SP may not be in the register list"); |
7417 |
"SP may not be in the register list"); |
| 7418 |
else if (ListContainsPC && ListContainsLR) |
7418 |
else if (ListContainsPC && ListContainsLR) |
| 7419 |
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), |
7419 |
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), |
| 7420 |
"PC and LR may not be in the register list simultaneously"); |
7420 |
"PC and LR may not be in the register list simultaneously"); |
| 7421 |
return false; |
7421 |
return false; |
| 7422 |
} |
7422 |
} |
| 7423 |
|
7423 |
|
| 7424 |
bool ARMAsmParser::validatetSTMRegList(const MCInst &Inst, |
7424 |
bool ARMAsmParser::validatetSTMRegList(const MCInst &Inst, |
| 7425 |
const OperandVector &Operands, |
7425 |
const OperandVector &Operands, |
| 7426 |
unsigned ListNo) { |
7426 |
unsigned ListNo) { |
| 7427 |
const ARMOperand &Op = static_cast(*Operands[ListNo]); |
7427 |
const ARMOperand &Op = static_cast(*Operands[ListNo]); |
| 7428 |
bool HasWritebackToken = Op.isToken() && Op.getToken() == "!"; |
7428 |
bool HasWritebackToken = Op.isToken() && Op.getToken() == "!"; |
| 7429 |
|
7429 |
|
| 7430 |
bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP); |
7430 |
bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP); |
| 7431 |
bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC); |
7431 |
bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC); |
| 7432 |
|
7432 |
|
| 7433 |
if (ListContainsSP && ListContainsPC) |
7433 |
if (ListContainsSP && ListContainsPC) |
| 7434 |
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), |
7434 |
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), |
| 7435 |
"SP and PC may not be in the register list"); |
7435 |
"SP and PC may not be in the register list"); |
| 7436 |
else if (ListContainsSP) |
7436 |
else if (ListContainsSP) |
| 7437 |
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), |
7437 |
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), |
| 7438 |
"SP may not be in the register list"); |
7438 |
"SP may not be in the register list"); |
| 7439 |
else if (ListContainsPC) |
7439 |
else if (ListContainsPC) |
| 7440 |
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), |
7440 |
return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), |
| 7441 |
"PC may not be in the register list"); |
7441 |
"PC may not be in the register list"); |
| 7442 |
return false; |
7442 |
return false; |
| 7443 |
} |
7443 |
} |
| 7444 |
|
7444 |
|
| 7445 |
bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, |
7445 |
bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, |
| 7446 |
const OperandVector &Operands, |
7446 |
const OperandVector &Operands, |
| 7447 |
bool Load, bool ARMMode, bool Writeback) { |
7447 |
bool Load, bool ARMMode, bool Writeback) { |
| 7448 |
unsigned RtIndex = Load || !Writeback ? 0 : 1; |
7448 |
unsigned RtIndex = Load || !Writeback ? 0 : 1; |
| 7449 |
unsigned Rt = MRI->getEncodingValue(Inst.getOperand(RtIndex).getReg()); |
7449 |
unsigned Rt = MRI->getEncodingValue(Inst.getOperand(RtIndex).getReg()); |
| 7450 |
unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(RtIndex + 1).getReg()); |
7450 |
unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(RtIndex + 1).getReg()); |
| 7451 |
|
7451 |
|
| 7452 |
if (ARMMode) { |
7452 |
if (ARMMode) { |
| 7453 |
// Rt can't be R14. |
7453 |
// Rt can't be R14. |
| 7454 |
if (Rt == 14) |
7454 |
if (Rt == 14) |
| 7455 |
return Error(Operands[3]->getStartLoc(), |
7455 |
return Error(Operands[3]->getStartLoc(), |
| 7456 |
"Rt can't be R14"); |
7456 |
"Rt can't be R14"); |
| 7457 |
|
7457 |
|
| 7458 |
// Rt must be even-numbered. |
7458 |
// Rt must be even-numbered. |
| 7459 |
if ((Rt & 1) == 1) |
7459 |
if ((Rt & 1) == 1) |
| 7460 |
return Error(Operands[3]->getStartLoc(), |
7460 |
return Error(Operands[3]->getStartLoc(), |
| 7461 |
"Rt must be even-numbered"); |
7461 |
"Rt must be even-numbered"); |
| 7462 |
|
7462 |
|
| 7463 |
// Rt2 must be Rt + 1. |
7463 |
// Rt2 must be Rt + 1. |
| 7464 |
if (Rt2 != Rt + 1) { |
7464 |
if (Rt2 != Rt + 1) { |
| 7465 |
if (Load) |
7465 |
if (Load) |
| 7466 |
return Error(Operands[3]->getStartLoc(), |
7466 |
return Error(Operands[3]->getStartLoc(), |
| 7467 |
"destination operands must be sequential"); |
7467 |
"destination operands must be sequential"); |
| 7468 |
else |
7468 |
else |
| 7469 |
return Error(Operands[3]->getStartLoc(), |
7469 |
return Error(Operands[3]->getStartLoc(), |
| 7470 |
"source operands must be sequential"); |
7470 |
"source operands must be sequential"); |
| 7471 |
} |
7471 |
} |
| 7472 |
|
7472 |
|
| 7473 |
// FIXME: Diagnose m == 15 |
7473 |
// FIXME: Diagnose m == 15 |
| 7474 |
// FIXME: Diagnose ldrd with m == t || m == t2. |
7474 |
// FIXME: Diagnose ldrd with m == t || m == t2. |
| 7475 |
} |
7475 |
} |
| 7476 |
|
7476 |
|
| 7477 |
if (!ARMMode && Load) { |
7477 |
if (!ARMMode && Load) { |
| 7478 |
if (Rt2 == Rt) |
7478 |
if (Rt2 == Rt) |
| 7479 |
return Error(Operands[3]->getStartLoc(), |
7479 |
return Error(Operands[3]->getStartLoc(), |
| 7480 |
"destination operands can't be identical"); |
7480 |
"destination operands can't be identical"); |
| 7481 |
} |
7481 |
} |
| 7482 |
|
7482 |
|
| 7483 |
if (Writeback) { |
7483 |
if (Writeback) { |
| 7484 |
unsigned Rn = MRI->getEncodingValue(Inst.getOperand(3).getReg()); |
7484 |
unsigned Rn = MRI->getEncodingValue(Inst.getOperand(3).getReg()); |
| 7485 |
|
7485 |
|
| 7486 |
if (Rn == Rt || Rn == Rt2) { |
7486 |
if (Rn == Rt || Rn == Rt2) { |
| 7487 |
if (Load) |
7487 |
if (Load) |
| 7488 |
return Error(Operands[3]->getStartLoc(), |
7488 |
return Error(Operands[3]->getStartLoc(), |
| 7489 |
"base register needs to be different from destination " |
7489 |
"base register needs to be different from destination " |
| 7490 |
"registers"); |
7490 |
"registers"); |
| 7491 |
else |
7491 |
else |
| 7492 |
return Error(Operands[3]->getStartLoc(), |
7492 |
return Error(Operands[3]->getStartLoc(), |
| 7493 |
"source register and base register can't be identical"); |
7493 |
"source register and base register can't be identical"); |
| 7494 |
} |
7494 |
} |
| 7495 |
|
7495 |
|
| 7496 |
// FIXME: Diagnose ldrd/strd with writeback and n == 15. |
7496 |
// FIXME: Diagnose ldrd/strd with writeback and n == 15. |
| 7497 |
// (Except the immediate form of ldrd?) |
7497 |
// (Except the immediate form of ldrd?) |
| 7498 |
} |
7498 |
} |
| 7499 |
|
7499 |
|
| 7500 |
return false; |
7500 |
return false; |
| 7501 |
} |
7501 |
} |
| 7502 |
|
7502 |
|
| 7503 |
static int findFirstVectorPredOperandIdx(const MCInstrDesc &MCID) { |
7503 |
static int findFirstVectorPredOperandIdx(const MCInstrDesc &MCID) { |
| 7504 |
for (unsigned i = 0; i < MCID.NumOperands; ++i) { |
7504 |
for (unsigned i = 0; i < MCID.NumOperands; ++i) { |
| 7505 |
if (ARM::isVpred(MCID.operands()[i].OperandType)) |
7505 |
if (ARM::isVpred(MCID.operands()[i].OperandType)) |
| 7506 |
return i; |
7506 |
return i; |
| 7507 |
} |
7507 |
} |
| 7508 |
return -1; |
7508 |
return -1; |
| 7509 |
} |
7509 |
} |
| 7510 |
|
7510 |
|
| 7511 |
static bool isVectorPredicable(const MCInstrDesc &MCID) { |
7511 |
static bool isVectorPredicable(const MCInstrDesc &MCID) { |
| 7512 |
return findFirstVectorPredOperandIdx(MCID) != -1; |
7512 |
return findFirstVectorPredOperandIdx(MCID) != -1; |
| 7513 |
} |
7513 |
} |
| 7514 |
|
7514 |
|
| 7515 |
static bool isARMMCExpr(MCParsedAsmOperand &MCOp) { |
7515 |
static bool isARMMCExpr(MCParsedAsmOperand &MCOp) { |
| 7516 |
ARMOperand &Op = static_cast(MCOp); |
7516 |
ARMOperand &Op = static_cast(MCOp); |
| 7517 |
if (!Op.isImm()) |
7517 |
if (!Op.isImm()) |
| 7518 |
return false; |
7518 |
return false; |
| 7519 |
const MCConstantExpr *CE = dyn_cast(Op.getImm()); |
7519 |
const MCConstantExpr *CE = dyn_cast(Op.getImm()); |
| 7520 |
if (CE) |
7520 |
if (CE) |
| 7521 |
return false; |
7521 |
return false; |
| 7522 |
const MCExpr *E = dyn_cast(Op.getImm()); |
7522 |
const MCExpr *E = dyn_cast(Op.getImm()); |
| 7523 |
if (!E) |
7523 |
if (!E) |
| 7524 |
return false; |
7524 |
return false; |
| 7525 |
return true; |
7525 |
return true; |
| 7526 |
} |
7526 |
} |
| 7527 |
|
7527 |
|
| 7528 |
// FIXME: We would really like to be able to tablegen'erate this. |
7528 |
// FIXME: We would really like to be able to tablegen'erate this. |
| 7529 |
bool ARMAsmParser::validateInstruction(MCInst &Inst, |
7529 |
bool ARMAsmParser::validateInstruction(MCInst &Inst, |
| 7530 |
const OperandVector &Operands) { |
7530 |
const OperandVector &Operands) { |
| 7531 |
const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); |
7531 |
const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); |
| 7532 |
SMLoc Loc = Operands[0]->getStartLoc(); |
7532 |
SMLoc Loc = Operands[0]->getStartLoc(); |
| 7533 |
|
7533 |
|
| 7534 |
// Check the IT block state first. |
7534 |
// Check the IT block state first. |
| 7535 |
// NOTE: BKPT and HLT instructions have the interesting property of being |
7535 |
// NOTE: BKPT and HLT instructions have the interesting property of being |
| 7536 |
// allowed in IT blocks, but not being predicable. They just always execute. |
7536 |
// allowed in IT blocks, but not being predicable. They just always execute. |
| 7537 |
if (inITBlock() && !instIsBreakpoint(Inst)) { |
7537 |
if (inITBlock() && !instIsBreakpoint(Inst)) { |
| 7538 |
// The instruction must be predicable. |
7538 |
// The instruction must be predicable. |
| 7539 |
if (!MCID.isPredicable()) |
7539 |
if (!MCID.isPredicable()) |
| 7540 |
return Error(Loc, "instructions in IT block must be predicable"); |
7540 |
return Error(Loc, "instructions in IT block must be predicable"); |
| 7541 |
ARMCC::CondCodes Cond = ARMCC::CondCodes( |
7541 |
ARMCC::CondCodes Cond = ARMCC::CondCodes( |
| 7542 |
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm()); |
7542 |
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm()); |
| 7543 |
if (Cond != currentITCond()) { |
7543 |
if (Cond != currentITCond()) { |
| 7544 |
// Find the condition code Operand to get its SMLoc information. |
7544 |
// Find the condition code Operand to get its SMLoc information. |
| 7545 |
SMLoc CondLoc; |
7545 |
SMLoc CondLoc; |
| 7546 |
for (unsigned I = 1; I < Operands.size(); ++I) |
7546 |
for (unsigned I = 1; I < Operands.size(); ++I) |
| 7547 |
if (static_cast(*Operands[I]).isCondCode()) |
7547 |
if (static_cast(*Operands[I]).isCondCode()) |
| 7548 |
CondLoc = Operands[I]->getStartLoc(); |
7548 |
CondLoc = Operands[I]->getStartLoc(); |
| 7549 |
return Error(CondLoc, "incorrect condition in IT block; got '" + |
7549 |
return Error(CondLoc, "incorrect condition in IT block; got '" + |
| 7550 |
StringRef(ARMCondCodeToString(Cond)) + |
7550 |
StringRef(ARMCondCodeToString(Cond)) + |
| 7551 |
"', but expected '" + |
7551 |
"', but expected '" + |
| 7552 |
ARMCondCodeToString(currentITCond()) + "'"); |
7552 |
ARMCondCodeToString(currentITCond()) + "'"); |
| 7553 |
} |
7553 |
} |
| 7554 |
// Check for non-'al' condition codes outside of the IT block. |
7554 |
// Check for non-'al' condition codes outside of the IT block. |
| 7555 |
} else if (isThumbTwo() && MCID.isPredicable() && |
7555 |
} else if (isThumbTwo() && MCID.isPredicable() && |
| 7556 |
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() != |
7556 |
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() != |
| 7557 |
ARMCC::AL && Inst.getOpcode() != ARM::tBcc && |
7557 |
ARMCC::AL && Inst.getOpcode() != ARM::tBcc && |
| 7558 |
Inst.getOpcode() != ARM::t2Bcc && |
7558 |
Inst.getOpcode() != ARM::t2Bcc && |
| 7559 |
Inst.getOpcode() != ARM::t2BFic) { |
7559 |
Inst.getOpcode() != ARM::t2BFic) { |
| 7560 |
return Error(Loc, "predicated instructions must be in IT block"); |
7560 |
return Error(Loc, "predicated instructions must be in IT block"); |
| 7561 |
} else if (!isThumb() && !useImplicitITARM() && MCID.isPredicable() && |
7561 |
} else if (!isThumb() && !useImplicitITARM() && MCID.isPredicable() && |
| 7562 |
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() != |
7562 |
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() != |
| 7563 |
ARMCC::AL) { |
7563 |
ARMCC::AL) { |
| 7564 |
return Warning(Loc, "predicated instructions should be in IT block"); |
7564 |
return Warning(Loc, "predicated instructions should be in IT block"); |
| 7565 |
} else if (!MCID.isPredicable()) { |
7565 |
} else if (!MCID.isPredicable()) { |
| 7566 |
// Check the instruction doesn't have a predicate operand anyway |
7566 |
// Check the instruction doesn't have a predicate operand anyway |
| 7567 |
// that it's not allowed to use. Sometimes this happens in order |
7567 |
// that it's not allowed to use. Sometimes this happens in order |
| 7568 |
// to keep instructions the same shape even though one cannot |
7568 |
// to keep instructions the same shape even though one cannot |
| 7569 |
// legally be predicated, e.g. vmul.f16 vs vmul.f32. |
7569 |
// legally be predicated, e.g. vmul.f16 vs vmul.f32. |
| 7570 |
for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) { |
7570 |
for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) { |
| 7571 |
if (MCID.operands()[i].isPredicate()) { |
7571 |
if (MCID.operands()[i].isPredicate()) { |
| 7572 |
if (Inst.getOperand(i).getImm() != ARMCC::AL) |
7572 |
if (Inst.getOperand(i).getImm() != ARMCC::AL) |
| 7573 |
return Error(Loc, "instruction is not predicable"); |
7573 |
return Error(Loc, "instruction is not predicable"); |
| 7574 |
break; |
7574 |
break; |
| 7575 |
} |
7575 |
} |
| 7576 |
} |
7576 |
} |
| 7577 |
} |
7577 |
} |
| 7578 |
|
7578 |
|
| 7579 |
// PC-setting instructions in an IT block, but not the last instruction of |
7579 |
// PC-setting instructions in an IT block, but not the last instruction of |
| 7580 |
// the block, are UNPREDICTABLE. |
7580 |
// the block, are UNPREDICTABLE. |
| 7581 |
if (inExplicitITBlock() && !lastInITBlock() && isITBlockTerminator(Inst)) { |
7581 |
if (inExplicitITBlock() && !lastInITBlock() && isITBlockTerminator(Inst)) { |
| 7582 |
return Error(Loc, "instruction must be outside of IT block or the last instruction in an IT block"); |
7582 |
return Error(Loc, "instruction must be outside of IT block or the last instruction in an IT block"); |
| 7583 |
} |
7583 |
} |
| 7584 |
|
7584 |
|
| 7585 |
if (inVPTBlock() && !instIsBreakpoint(Inst)) { |
7585 |
if (inVPTBlock() && !instIsBreakpoint(Inst)) { |
| 7586 |
unsigned Bit = extractITMaskBit(VPTState.Mask, VPTState.CurPosition); |
7586 |
unsigned Bit = extractITMaskBit(VPTState.Mask, VPTState.CurPosition); |
| 7587 |
if (!isVectorPredicable(MCID)) |
7587 |
if (!isVectorPredicable(MCID)) |
| 7588 |
return Error(Loc, "instruction in VPT block must be predicable"); |
7588 |
return Error(Loc, "instruction in VPT block must be predicable"); |
| 7589 |
unsigned Pred = Inst.getOperand(findFirstVectorPredOperandIdx(MCID)).getImm(); |
7589 |
unsigned Pred = Inst.getOperand(findFirstVectorPredOperandIdx(MCID)).getImm(); |
| 7590 |
unsigned VPTPred = Bit ? ARMVCC::Else : ARMVCC::Then; |
7590 |
unsigned VPTPred = Bit ? ARMVCC::Else : ARMVCC::Then; |
| 7591 |
if (Pred != VPTPred) { |
7591 |
if (Pred != VPTPred) { |
| 7592 |
SMLoc PredLoc; |
7592 |
SMLoc PredLoc; |
| 7593 |
for (unsigned I = 1; I < Operands.size(); ++I) |
7593 |
for (unsigned I = 1; I < Operands.size(); ++I) |
| 7594 |
if (static_cast(*Operands[I]).isVPTPred()) |
7594 |
if (static_cast(*Operands[I]).isVPTPred()) |
| 7595 |
PredLoc = Operands[I]->getStartLoc(); |
7595 |
PredLoc = Operands[I]->getStartLoc(); |
| 7596 |
return Error(PredLoc, "incorrect predication in VPT block; got '" + |
7596 |
return Error(PredLoc, "incorrect predication in VPT block; got '" + |
| 7597 |
StringRef(ARMVPTPredToString(ARMVCC::VPTCodes(Pred))) + |
7597 |
StringRef(ARMVPTPredToString(ARMVCC::VPTCodes(Pred))) + |
| 7598 |
"', but expected '" + |
7598 |
"', but expected '" + |
| 7599 |
ARMVPTPredToString(ARMVCC::VPTCodes(VPTPred)) + "'"); |
7599 |
ARMVPTPredToString(ARMVCC::VPTCodes(VPTPred)) + "'"); |
| 7600 |
} |
7600 |
} |
| 7601 |
} |
7601 |
} |
| 7602 |
else if (isVectorPredicable(MCID) && |
7602 |
else if (isVectorPredicable(MCID) && |
| 7603 |
Inst.getOperand(findFirstVectorPredOperandIdx(MCID)).getImm() != |
7603 |
Inst.getOperand(findFirstVectorPredOperandIdx(MCID)).getImm() != |
| 7604 |
ARMVCC::None) |
7604 |
ARMVCC::None) |
| 7605 |
return Error(Loc, "VPT predicated instructions must be in VPT block"); |
7605 |
return Error(Loc, "VPT predicated instructions must be in VPT block"); |
| 7606 |
|
7606 |
|
| 7607 |
const unsigned Opcode = Inst.getOpcode(); |
7607 |
const unsigned Opcode = Inst.getOpcode(); |
| 7608 |
switch (Opcode) { |
7608 |
switch (Opcode) { |
| 7609 |
case ARM::t2IT: { |
7609 |
case ARM::t2IT: { |
| 7610 |
// Encoding is unpredictable if it ever results in a notional 'NV' |
7610 |
// Encoding is unpredictable if it ever results in a notional 'NV' |
| 7611 |
// predicate. Since we don't parse 'NV' directly this means an 'AL' |
7611 |
// predicate. Since we don't parse 'NV' directly this means an 'AL' |
| 7612 |
// predicate with an "else" mask bit. |
7612 |
// predicate with an "else" mask bit. |
| 7613 |
unsigned Cond = Inst.getOperand(0).getImm(); |
7613 |
unsigned Cond = Inst.getOperand(0).getImm(); |
| 7614 |
unsigned Mask = Inst.getOperand(1).getImm(); |
7614 |
unsigned Mask = Inst.getOperand(1).getImm(); |
| 7615 |
|
7615 |
|
| 7616 |
// Conditions only allowing a 't' are those with no set bit except |
7616 |
// Conditions only allowing a 't' are those with no set bit except |
| 7617 |
// the lowest-order one that indicates the end of the sequence. In |
7617 |
// the lowest-order one that indicates the end of the sequence. In |
| 7618 |
// other words, powers of 2. |
7618 |
// other words, powers of 2. |
| 7619 |
if (Cond == ARMCC::AL && llvm::popcount(Mask) != 1) |
7619 |
if (Cond == ARMCC::AL && llvm::popcount(Mask) != 1) |
| 7620 |
return Error(Loc, "unpredictable IT predicate sequence"); |
7620 |
return Error(Loc, "unpredictable IT predicate sequence"); |
| 7621 |
break; |
7621 |
break; |
| 7622 |
} |
7622 |
} |
| 7623 |
case ARM::LDRD: |
7623 |
case ARM::LDRD: |
| 7624 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/true, |
7624 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/true, |
| 7625 |
/*Writeback*/false)) |
7625 |
/*Writeback*/false)) |
| 7626 |
return true; |
7626 |
return true; |
| 7627 |
break; |
7627 |
break; |
| 7628 |
case ARM::LDRD_PRE: |
7628 |
case ARM::LDRD_PRE: |
| 7629 |
case ARM::LDRD_POST: |
7629 |
case ARM::LDRD_POST: |
| 7630 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/true, |
7630 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/true, |
| 7631 |
/*Writeback*/true)) |
7631 |
/*Writeback*/true)) |
| 7632 |
return true; |
7632 |
return true; |
| 7633 |
break; |
7633 |
break; |
| 7634 |
case ARM::t2LDRDi8: |
7634 |
case ARM::t2LDRDi8: |
| 7635 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/false, |
7635 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/false, |
| 7636 |
/*Writeback*/false)) |
7636 |
/*Writeback*/false)) |
| 7637 |
return true; |
7637 |
return true; |
| 7638 |
break; |
7638 |
break; |
| 7639 |
case ARM::t2LDRD_PRE: |
7639 |
case ARM::t2LDRD_PRE: |
| 7640 |
case ARM::t2LDRD_POST: |
7640 |
case ARM::t2LDRD_POST: |
| 7641 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/false, |
7641 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/false, |
| 7642 |
/*Writeback*/true)) |
7642 |
/*Writeback*/true)) |
| 7643 |
return true; |
7643 |
return true; |
| 7644 |
break; |
7644 |
break; |
| 7645 |
case ARM::t2BXJ: { |
7645 |
case ARM::t2BXJ: { |
| 7646 |
const unsigned RmReg = Inst.getOperand(0).getReg(); |
7646 |
const unsigned RmReg = Inst.getOperand(0).getReg(); |
| 7647 |
// Rm = SP is no longer unpredictable in v8-A |
7647 |
// Rm = SP is no longer unpredictable in v8-A |
| 7648 |
if (RmReg == ARM::SP && !hasV8Ops()) |
7648 |
if (RmReg == ARM::SP && !hasV8Ops()) |
| 7649 |
return Error(Operands[2]->getStartLoc(), |
7649 |
return Error(Operands[2]->getStartLoc(), |
| 7650 |
"r13 (SP) is an unpredictable operand to BXJ"); |
7650 |
"r13 (SP) is an unpredictable operand to BXJ"); |
| 7651 |
return false; |
7651 |
return false; |
| 7652 |
} |
7652 |
} |
| 7653 |
case ARM::STRD: |
7653 |
case ARM::STRD: |
| 7654 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/true, |
7654 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/true, |
| 7655 |
/*Writeback*/false)) |
7655 |
/*Writeback*/false)) |
| 7656 |
return true; |
7656 |
return true; |
| 7657 |
break; |
7657 |
break; |
| 7658 |
case ARM::STRD_PRE: |
7658 |
case ARM::STRD_PRE: |
| 7659 |
case ARM::STRD_POST: |
7659 |
case ARM::STRD_POST: |
| 7660 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/true, |
7660 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/true, |
| 7661 |
/*Writeback*/true)) |
7661 |
/*Writeback*/true)) |
| 7662 |
return true; |
7662 |
return true; |
| 7663 |
break; |
7663 |
break; |
| 7664 |
case ARM::t2STRD_PRE: |
7664 |
case ARM::t2STRD_PRE: |
| 7665 |
case ARM::t2STRD_POST: |
7665 |
case ARM::t2STRD_POST: |
| 7666 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/false, |
7666 |
if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/false, |
| 7667 |
/*Writeback*/true)) |
7667 |
/*Writeback*/true)) |
| 7668 |
return true; |
7668 |
return true; |
| 7669 |
break; |
7669 |
break; |
| 7670 |
case ARM::STR_PRE_IMM: |
7670 |
case ARM::STR_PRE_IMM: |
| 7671 |
case ARM::STR_PRE_REG: |
7671 |
case ARM::STR_PRE_REG: |
| 7672 |
case ARM::t2STR_PRE: |
7672 |
case ARM::t2STR_PRE: |
| 7673 |
case ARM::STR_POST_IMM: |
7673 |
case ARM::STR_POST_IMM: |
| 7674 |
case ARM::STR_POST_REG: |
7674 |
case ARM::STR_POST_REG: |
| 7675 |
case ARM::t2STR_POST: |
7675 |
case ARM::t2STR_POST: |
| 7676 |
case ARM::STRH_PRE: |
7676 |
case ARM::STRH_PRE: |
| 7677 |
case ARM::t2STRH_PRE: |
7677 |
case ARM::t2STRH_PRE: |
| 7678 |
case ARM::STRH_POST: |
7678 |
case ARM::STRH_POST: |
| 7679 |
case ARM::t2STRH_POST: |
7679 |
case ARM::t2STRH_POST: |
| 7680 |
case ARM::STRB_PRE_IMM: |
7680 |
case ARM::STRB_PRE_IMM: |
| 7681 |
case ARM::STRB_PRE_REG: |
7681 |
case ARM::STRB_PRE_REG: |
| 7682 |
case ARM::t2STRB_PRE: |
7682 |
case ARM::t2STRB_PRE: |
| 7683 |
case ARM::STRB_POST_IMM: |
7683 |
case ARM::STRB_POST_IMM: |
| 7684 |
case ARM::STRB_POST_REG: |
7684 |
case ARM::STRB_POST_REG: |
| 7685 |
case ARM::t2STRB_POST: { |
7685 |
case ARM::t2STRB_POST: { |
| 7686 |
// Rt must be different from Rn. |
7686 |
// Rt must be different from Rn. |
| 7687 |
const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg()); |
7687 |
const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg()); |
| 7688 |
const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg()); |
7688 |
const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg()); |
| 7689 |
|
7689 |
|
| 7690 |
if (Rt == Rn) |
7690 |
if (Rt == Rn) |
| 7691 |
return Error(Operands[3]->getStartLoc(), |
7691 |
return Error(Operands[3]->getStartLoc(), |
| 7692 |
"source register and base register can't be identical"); |
7692 |
"source register and base register can't be identical"); |
| 7693 |
return false; |
7693 |
return false; |
| 7694 |
} |
7694 |
} |
| 7695 |
case ARM::t2LDR_PRE_imm: |
7695 |
case ARM::t2LDR_PRE_imm: |
| 7696 |
case ARM::t2LDR_POST_imm: |
7696 |
case ARM::t2LDR_POST_imm: |
| 7697 |
case ARM::t2STR_PRE_imm: |
7697 |
case ARM::t2STR_PRE_imm: |
| 7698 |
case ARM::t2STR_POST_imm: { |
7698 |
case ARM::t2STR_POST_imm: { |
| 7699 |
// Rt must be different from Rn. |
7699 |
// Rt must be different from Rn. |
| 7700 |
const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); |
7700 |
const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); |
| 7701 |
const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(1).getReg()); |
7701 |
const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(1).getReg()); |
| 7702 |
|
7702 |
|
| 7703 |
if (Rt == Rn) |
7703 |
if (Rt == Rn) |
| 7704 |
return Error(Operands[3]->getStartLoc(), |
7704 |
return Error(Operands[3]->getStartLoc(), |
| 7705 |
"destination register and base register can't be identical"); |
7705 |
"destination register and base register can't be identical"); |
| 7706 |
if (Inst.getOpcode() == ARM::t2LDR_POST_imm || |
7706 |
if (Inst.getOpcode() == ARM::t2LDR_POST_imm || |
| 7707 |
Inst.getOpcode() == ARM::t2STR_POST_imm) { |
7707 |
Inst.getOpcode() == ARM::t2STR_POST_imm) { |
| 7708 |
int Imm = Inst.getOperand(2).getImm(); |
7708 |
int Imm = Inst.getOperand(2).getImm(); |
| 7709 |
if (Imm > 255 || Imm < -255) |
7709 |
if (Imm > 255 || Imm < -255) |
| 7710 |
return Error(Operands[5]->getStartLoc(), |
7710 |
return Error(Operands[5]->getStartLoc(), |
| 7711 |
"operand must be in range [-255, 255]"); |
7711 |
"operand must be in range [-255, 255]"); |
| 7712 |
} |
7712 |
} |
| 7713 |
if (Inst.getOpcode() == ARM::t2STR_PRE_imm || |
7713 |
if (Inst.getOpcode() == ARM::t2STR_PRE_imm || |
| 7714 |
Inst.getOpcode() == ARM::t2STR_POST_imm) { |
7714 |
Inst.getOpcode() == ARM::t2STR_POST_imm) { |
| 7715 |
if (Inst.getOperand(0).getReg() == ARM::PC) { |
7715 |
if (Inst.getOperand(0).getReg() == ARM::PC) { |
| 7716 |
return Error(Operands[3]->getStartLoc(), |
7716 |
return Error(Operands[3]->getStartLoc(), |
| 7717 |
"operand must be a register in range [r0, r14]"); |
7717 |
"operand must be a register in range [r0, r14]"); |
| 7718 |
} |
7718 |
} |
| 7719 |
} |
7719 |
} |
| 7720 |
return false; |
7720 |
return false; |
| 7721 |
} |
7721 |
} |
| 7722 |
|
7722 |
|
| 7723 |
case ARM::t2LDRB_OFFSET_imm: |
7723 |
case ARM::t2LDRB_OFFSET_imm: |
| 7724 |
case ARM::t2LDRB_PRE_imm: |
7724 |
case ARM::t2LDRB_PRE_imm: |
| 7725 |
case ARM::t2LDRB_POST_imm: |
7725 |
case ARM::t2LDRB_POST_imm: |
| 7726 |
case ARM::t2STRB_OFFSET_imm: |
7726 |
case ARM::t2STRB_OFFSET_imm: |
| 7727 |
case ARM::t2STRB_PRE_imm: |
7727 |
case ARM::t2STRB_PRE_imm: |
| 7728 |
case ARM::t2STRB_POST_imm: { |
7728 |
case ARM::t2STRB_POST_imm: { |
| 7729 |
if (Inst.getOpcode() == ARM::t2LDRB_POST_imm || |
7729 |
if (Inst.getOpcode() == ARM::t2LDRB_POST_imm || |
| 7730 |
Inst.getOpcode() == ARM::t2STRB_POST_imm || |
7730 |
Inst.getOpcode() == ARM::t2STRB_POST_imm || |
| 7731 |
Inst.getOpcode() == ARM::t2LDRB_PRE_imm || |
7731 |
Inst.getOpcode() == ARM::t2LDRB_PRE_imm || |
| 7732 |
Inst.getOpcode() == ARM::t2STRB_PRE_imm) { |
7732 |
Inst.getOpcode() == ARM::t2STRB_PRE_imm) { |
| 7733 |
int Imm = Inst.getOperand(2).getImm(); |
7733 |
int Imm = Inst.getOperand(2).getImm(); |
| 7734 |
if (Imm > 255 || Imm < -255) |
7734 |
if (Imm > 255 || Imm < -255) |
| 7735 |
return Error(Operands[5]->getStartLoc(), |
7735 |
return Error(Operands[5]->getStartLoc(), |
| 7736 |
"operand must be in range [-255, 255]"); |
7736 |
"operand must be in range [-255, 255]"); |
| 7737 |
} else if (Inst.getOpcode() == ARM::t2LDRB_OFFSET_imm || |
7737 |
} else if (Inst.getOpcode() == ARM::t2LDRB_OFFSET_imm || |
| 7738 |
Inst.getOpcode() == ARM::t2STRB_OFFSET_imm) { |
7738 |
Inst.getOpcode() == ARM::t2STRB_OFFSET_imm) { |
| 7739 |
int Imm = Inst.getOperand(2).getImm(); |
7739 |
int Imm = Inst.getOperand(2).getImm(); |
| 7740 |
if (Imm > 0 || Imm < -255) |
7740 |
if (Imm > 0 || Imm < -255) |
| 7741 |
return Error(Operands[5]->getStartLoc(), |
7741 |
return Error(Operands[5]->getStartLoc(), |
| 7742 |
"operand must be in range [0, 255] with a negative sign"); |
7742 |
"operand must be in range [0, 255] with a negative sign"); |
| 7743 |
} |
7743 |
} |
| 7744 |
if (Inst.getOperand(0).getReg() == ARM::PC) { |
7744 |
if (Inst.getOperand(0).getReg() == ARM::PC) { |
| 7745 |
return Error(Operands[3]->getStartLoc(), |
7745 |
return Error(Operands[3]->getStartLoc(), |
| 7746 |
"if operand is PC, should call the LDRB (literal)"); |
7746 |
"if operand is PC, should call the LDRB (literal)"); |
| 7747 |
} |
7747 |
} |
| 7748 |
return false; |
7748 |
return false; |
| 7749 |
} |
7749 |
} |
| 7750 |
|
7750 |
|
| 7751 |
case ARM::t2LDRH_OFFSET_imm: |
7751 |
case ARM::t2LDRH_OFFSET_imm: |
| 7752 |
case ARM::t2LDRH_PRE_imm: |
7752 |
case ARM::t2LDRH_PRE_imm: |
| 7753 |
case ARM::t2LDRH_POST_imm: |
7753 |
case ARM::t2LDRH_POST_imm: |
| 7754 |
case ARM::t2STRH_OFFSET_imm: |
7754 |
case ARM::t2STRH_OFFSET_imm: |
| 7755 |
case ARM::t2STRH_PRE_imm: |
7755 |
case ARM::t2STRH_PRE_imm: |
| 7756 |
case ARM::t2STRH_POST_imm: { |
7756 |
case ARM::t2STRH_POST_imm: { |
| 7757 |
if (Inst.getOpcode() == ARM::t2LDRH_POST_imm || |
7757 |
if (Inst.getOpcode() == ARM::t2LDRH_POST_imm || |
| 7758 |
Inst.getOpcode() == ARM::t2STRH_POST_imm || |
7758 |
Inst.getOpcode() == ARM::t2STRH_POST_imm || |
| 7759 |
Inst.getOpcode() == ARM::t2LDRH_PRE_imm || |
7759 |
Inst.getOpcode() == ARM::t2LDRH_PRE_imm || |
| 7760 |
Inst.getOpcode() == ARM::t2STRH_PRE_imm) { |
7760 |
Inst.getOpcode() == ARM::t2STRH_PRE_imm) { |
| 7761 |
int Imm = Inst.getOperand(2).getImm(); |
7761 |
int Imm = Inst.getOperand(2).getImm(); |
| 7762 |
if (Imm > 255 || Imm < -255) |
7762 |
if (Imm > 255 || Imm < -255) |
| 7763 |
return Error(Operands[5]->getStartLoc(), |
7763 |
return Error(Operands[5]->getStartLoc(), |
| 7764 |
"operand must be in range [-255, 255]"); |
7764 |
"operand must be in range [-255, 255]"); |
| 7765 |
} else if (Inst.getOpcode() == ARM::t2LDRH_OFFSET_imm || |
7765 |
} else if (Inst.getOpcode() == ARM::t2LDRH_OFFSET_imm || |
| 7766 |
Inst.getOpcode() == ARM::t2STRH_OFFSET_imm) { |
7766 |
Inst.getOpcode() == ARM::t2STRH_OFFSET_imm) { |
| 7767 |
int Imm = Inst.getOperand(2).getImm(); |
7767 |
int Imm = Inst.getOperand(2).getImm(); |
| 7768 |
if (Imm > 0 || Imm < -255) |
7768 |
if (Imm > 0 || Imm < -255) |
| 7769 |
return Error(Operands[5]->getStartLoc(), |
7769 |
return Error(Operands[5]->getStartLoc(), |
| 7770 |
"operand must be in range [0, 255] with a negative sign"); |
7770 |
"operand must be in range [0, 255] with a negative sign"); |
| 7771 |
} |
7771 |
} |
| 7772 |
if (Inst.getOperand(0).getReg() == ARM::PC) { |
7772 |
if (Inst.getOperand(0).getReg() == ARM::PC) { |
| 7773 |
return Error(Operands[3]->getStartLoc(), |
7773 |
return Error(Operands[3]->getStartLoc(), |
| 7774 |
"if operand is PC, should call the LDRH (literal)"); |
7774 |
"if operand is PC, should call the LDRH (literal)"); |
| 7775 |
} |
7775 |
} |
| 7776 |
return false; |
7776 |
return false; |
| 7777 |
} |
7777 |
} |
| 7778 |
|
7778 |
|
| 7779 |
case ARM::t2LDRSB_OFFSET_imm: |
7779 |
case ARM::t2LDRSB_OFFSET_imm: |
| 7780 |
case ARM::t2LDRSB_PRE_imm: |
7780 |
case ARM::t2LDRSB_PRE_imm: |
| 7781 |
case ARM::t2LDRSB_POST_imm: { |
7781 |
case ARM::t2LDRSB_POST_imm: { |
| 7782 |
if (Inst.getOpcode() == ARM::t2LDRSB_POST_imm || |
7782 |
if (Inst.getOpcode() == ARM::t2LDRSB_POST_imm || |
| 7783 |
Inst.getOpcode() == ARM::t2LDRSB_PRE_imm) { |
7783 |
Inst.getOpcode() == ARM::t2LDRSB_PRE_imm) { |
| 7784 |
int Imm = Inst.getOperand(2).getImm(); |
7784 |
int Imm = Inst.getOperand(2).getImm(); |
| 7785 |
if (Imm > 255 || Imm < -255) |
7785 |
if (Imm > 255 || Imm < -255) |
| 7786 |
return Error(Operands[5]->getStartLoc(), |
7786 |
return Error(Operands[5]->getStartLoc(), |
| 7787 |
"operand must be in range [-255, 255]"); |
7787 |
"operand must be in range [-255, 255]"); |
| 7788 |
} else if (Inst.getOpcode() == ARM::t2LDRSB_OFFSET_imm) { |
7788 |
} else if (Inst.getOpcode() == ARM::t2LDRSB_OFFSET_imm) { |
| 7789 |
int Imm = Inst.getOperand(2).getImm(); |
7789 |
int Imm = Inst.getOperand(2).getImm(); |
| 7790 |
if (Imm > 0 || Imm < -255) |
7790 |
if (Imm > 0 || Imm < -255) |
| 7791 |
return Error(Operands[5]->getStartLoc(), |
7791 |
return Error(Operands[5]->getStartLoc(), |
| 7792 |
"operand must be in range [0, 255] with a negative sign"); |
7792 |
"operand must be in range [0, 255] with a negative sign"); |
| 7793 |
} |
7793 |
} |
| 7794 |
if (Inst.getOperand(0).getReg() == ARM::PC) { |
7794 |
if (Inst.getOperand(0).getReg() == ARM::PC) { |
| 7795 |
return Error(Operands[3]->getStartLoc(), |
7795 |
return Error(Operands[3]->getStartLoc(), |
| 7796 |
"if operand is PC, should call the LDRH (literal)"); |
7796 |
"if operand is PC, should call the LDRH (literal)"); |
| 7797 |
} |
7797 |
} |
| 7798 |
return false; |
7798 |
return false; |
| 7799 |
} |
7799 |
} |
| 7800 |
|
7800 |
|
| 7801 |
case ARM::t2LDRSH_OFFSET_imm: |
7801 |
case ARM::t2LDRSH_OFFSET_imm: |
| 7802 |
case ARM::t2LDRSH_PRE_imm: |
7802 |
case ARM::t2LDRSH_PRE_imm: |
| 7803 |
case ARM::t2LDRSH_POST_imm: { |
7803 |
case ARM::t2LDRSH_POST_imm: { |
| 7804 |
if (Inst.getOpcode() == ARM::t2LDRSH_POST_imm || |
7804 |
if (Inst.getOpcode() == ARM::t2LDRSH_POST_imm || |
| 7805 |
Inst.getOpcode() == ARM::t2LDRSH_PRE_imm) { |
7805 |
Inst.getOpcode() == ARM::t2LDRSH_PRE_imm) { |
| 7806 |
int Imm = Inst.getOperand(2).getImm(); |
7806 |
int Imm = Inst.getOperand(2).getImm(); |
| 7807 |
if (Imm > 255 || Imm < -255) |
7807 |
if (Imm > 255 || Imm < -255) |
| 7808 |
return Error(Operands[5]->getStartLoc(), |
7808 |
return Error(Operands[5]->getStartLoc(), |
| 7809 |
"operand must be in range [-255, 255]"); |
7809 |
"operand must be in range [-255, 255]"); |
| 7810 |
} else if (Inst.getOpcode() == ARM::t2LDRSH_OFFSET_imm) { |
7810 |
} else if (Inst.getOpcode() == ARM::t2LDRSH_OFFSET_imm) { |
| 7811 |
int Imm = Inst.getOperand(2).getImm(); |
7811 |
int Imm = Inst.getOperand(2).getImm(); |
| 7812 |
if (Imm > 0 || Imm < -255) |
7812 |
if (Imm > 0 || Imm < -255) |
| 7813 |
return Error(Operands[5]->getStartLoc(), |
7813 |
return Error(Operands[5]->getStartLoc(), |
| 7814 |
"operand must be in range [0, 255] with a negative sign"); |
7814 |
"operand must be in range [0, 255] with a negative sign"); |
| 7815 |
} |
7815 |
} |
| 7816 |
if (Inst.getOperand(0).getReg() == ARM::PC) { |
7816 |
if (Inst.getOperand(0).getReg() == ARM::PC) { |
| 7817 |
return Error(Operands[3]->getStartLoc(), |
7817 |
return Error(Operands[3]->getStartLoc(), |
| 7818 |
"if operand is PC, should call the LDRH (literal)"); |
7818 |
"if operand is PC, should call the LDRH (literal)"); |
| 7819 |
} |
7819 |
} |
| 7820 |
return false; |
7820 |
return false; |
| 7821 |
} |
7821 |
} |
| 7822 |
|
7822 |
|
| 7823 |
case ARM::LDR_PRE_IMM: |
7823 |
case ARM::LDR_PRE_IMM: |
| 7824 |
case ARM::LDR_PRE_REG: |
7824 |
case ARM::LDR_PRE_REG: |
| 7825 |
case ARM::t2LDR_PRE: |
7825 |
case ARM::t2LDR_PRE: |
| 7826 |
case ARM::LDR_POST_IMM: |
7826 |
case ARM::LDR_POST_IMM: |
| 7827 |
case ARM::LDR_POST_REG: |
7827 |
case ARM::LDR_POST_REG: |
| 7828 |
case ARM::t2LDR_POST: |
7828 |
case ARM::t2LDR_POST: |
| 7829 |
case ARM::LDRH_PRE: |
7829 |
case ARM::LDRH_PRE: |
| 7830 |
case ARM::t2LDRH_PRE: |
7830 |
case ARM::t2LDRH_PRE: |
| 7831 |
case ARM::LDRH_POST: |
7831 |
case ARM::LDRH_POST: |
| 7832 |
case ARM::t2LDRH_POST: |
7832 |
case ARM::t2LDRH_POST: |
| 7833 |
case ARM::LDRSH_PRE: |
7833 |
case ARM::LDRSH_PRE: |
| 7834 |
case ARM::t2LDRSH_PRE: |
7834 |
case ARM::t2LDRSH_PRE: |
| 7835 |
case ARM::LDRSH_POST: |
7835 |
case ARM::LDRSH_POST: |
| 7836 |
case ARM::t2LDRSH_POST: |
7836 |
case ARM::t2LDRSH_POST: |
| 7837 |
case ARM::LDRB_PRE_IMM: |
7837 |
case ARM::LDRB_PRE_IMM: |
| 7838 |
case ARM::LDRB_PRE_REG: |
7838 |
case ARM::LDRB_PRE_REG: |
| 7839 |
case ARM::t2LDRB_PRE: |
7839 |
case ARM::t2LDRB_PRE: |
| 7840 |
case ARM::LDRB_POST_IMM: |
7840 |
case ARM::LDRB_POST_IMM: |
| 7841 |
case ARM::LDRB_POST_REG: |
7841 |
case ARM::LDRB_POST_REG: |
| 7842 |
case ARM::t2LDRB_POST: |
7842 |
case ARM::t2LDRB_POST: |
| 7843 |
case ARM::LDRSB_PRE: |
7843 |
case ARM::LDRSB_PRE: |
| 7844 |
case ARM::t2LDRSB_PRE: |
7844 |
case ARM::t2LDRSB_PRE: |
| 7845 |
case ARM::LDRSB_POST: |
7845 |
case ARM::LDRSB_POST: |
| 7846 |
case ARM::t2LDRSB_POST: { |
7846 |
case ARM::t2LDRSB_POST: { |
| 7847 |
// Rt must be different from Rn. |
7847 |
// Rt must be different from Rn. |
| 7848 |
const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); |
7848 |
const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); |
| 7849 |
const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg()); |
7849 |
const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg()); |
| 7850 |
|
7850 |
|
| 7851 |
if (Rt == Rn) |
7851 |
if (Rt == Rn) |
| 7852 |
return Error(Operands[3]->getStartLoc(), |
7852 |
return Error(Operands[3]->getStartLoc(), |
| 7853 |
"destination register and base register can't be identical"); |
7853 |
"destination register and base register can't be identical"); |
| 7854 |
return false; |
7854 |
return false; |
| 7855 |
} |
7855 |
} |
| 7856 |
|
7856 |
|
| 7857 |
case ARM::MVE_VLDRBU8_rq: |
7857 |
case ARM::MVE_VLDRBU8_rq: |
| 7858 |
case ARM::MVE_VLDRBU16_rq: |
7858 |
case ARM::MVE_VLDRBU16_rq: |
| 7859 |
case ARM::MVE_VLDRBS16_rq: |
7859 |
case ARM::MVE_VLDRBS16_rq: |
| 7860 |
case ARM::MVE_VLDRBU32_rq: |
7860 |
case ARM::MVE_VLDRBU32_rq: |
| 7861 |
case ARM::MVE_VLDRBS32_rq: |
7861 |
case ARM::MVE_VLDRBS32_rq: |
| 7862 |
case ARM::MVE_VLDRHU16_rq: |
7862 |
case ARM::MVE_VLDRHU16_rq: |
| 7863 |
case ARM::MVE_VLDRHU16_rq_u: |
7863 |
case ARM::MVE_VLDRHU16_rq_u: |
| 7864 |
case ARM::MVE_VLDRHU32_rq: |
7864 |
case ARM::MVE_VLDRHU32_rq: |
| 7865 |
case ARM::MVE_VLDRHU32_rq_u: |
7865 |
case ARM::MVE_VLDRHU32_rq_u: |
| 7866 |
case ARM::MVE_VLDRHS32_rq: |
7866 |
case ARM::MVE_VLDRHS32_rq: |
| 7867 |
case ARM::MVE_VLDRHS32_rq_u: |
7867 |
case ARM::MVE_VLDRHS32_rq_u: |
| 7868 |
case ARM::MVE_VLDRWU32_rq: |
7868 |
case ARM::MVE_VLDRWU32_rq: |
| 7869 |
case ARM::MVE_VLDRWU32_rq_u: |
7869 |
case ARM::MVE_VLDRWU32_rq_u: |
| 7870 |
case ARM::MVE_VLDRDU64_rq: |
7870 |
case ARM::MVE_VLDRDU64_rq: |
| 7871 |
case ARM::MVE_VLDRDU64_rq_u: |
7871 |
case ARM::MVE_VLDRDU64_rq_u: |
| 7872 |
case ARM::MVE_VLDRWU32_qi: |
7872 |
case ARM::MVE_VLDRWU32_qi: |
| 7873 |
case ARM::MVE_VLDRWU32_qi_pre: |
7873 |
case ARM::MVE_VLDRWU32_qi_pre: |
| 7874 |
case ARM::MVE_VLDRDU64_qi: |
7874 |
case ARM::MVE_VLDRDU64_qi: |
| 7875 |
case ARM::MVE_VLDRDU64_qi_pre: { |
7875 |
case ARM::MVE_VLDRDU64_qi_pre: { |
| 7876 |
// Qd must be different from Qm. |
7876 |
// Qd must be different from Qm. |
| 7877 |
unsigned QdIdx = 0, QmIdx = 2; |
7877 |
unsigned QdIdx = 0, QmIdx = 2; |
| 7878 |
bool QmIsPointer = false; |
7878 |
bool QmIsPointer = false; |
| 7879 |
switch (Opcode) { |
7879 |
switch (Opcode) { |
| 7880 |
case ARM::MVE_VLDRWU32_qi: |
7880 |
case ARM::MVE_VLDRWU32_qi: |
| 7881 |
case ARM::MVE_VLDRDU64_qi: |
7881 |
case ARM::MVE_VLDRDU64_qi: |
| 7882 |
QmIdx = 1; |
7882 |
QmIdx = 1; |
| 7883 |
QmIsPointer = true; |
7883 |
QmIsPointer = true; |
| 7884 |
break; |
7884 |
break; |
| 7885 |
case ARM::MVE_VLDRWU32_qi_pre: |
7885 |
case ARM::MVE_VLDRWU32_qi_pre: |
| 7886 |
case ARM::MVE_VLDRDU64_qi_pre: |
7886 |
case ARM::MVE_VLDRDU64_qi_pre: |
| 7887 |
QdIdx = 1; |
7887 |
QdIdx = 1; |
| 7888 |
QmIsPointer = true; |
7888 |
QmIsPointer = true; |
| 7889 |
break; |
7889 |
break; |
| 7890 |
} |
7890 |
} |
| 7891 |
|
7891 |
|
| 7892 |
const unsigned Qd = MRI->getEncodingValue(Inst.getOperand(QdIdx).getReg()); |
7892 |
const unsigned Qd = MRI->getEncodingValue(Inst.getOperand(QdIdx).getReg()); |
| 7893 |
const unsigned Qm = MRI->getEncodingValue(Inst.getOperand(QmIdx).getReg()); |
7893 |
const unsigned Qm = MRI->getEncodingValue(Inst.getOperand(QmIdx).getReg()); |
| 7894 |
|
7894 |
|
| 7895 |
if (Qd == Qm) { |
7895 |
if (Qd == Qm) { |
| 7896 |
return Error(Operands[3]->getStartLoc(), |
7896 |
return Error(Operands[3]->getStartLoc(), |
| 7897 |
Twine("destination vector register and vector ") + |
7897 |
Twine("destination vector register and vector ") + |
| 7898 |
(QmIsPointer ? "pointer" : "offset") + |
7898 |
(QmIsPointer ? "pointer" : "offset") + |
| 7899 |
" register can't be identical"); |
7899 |
" register can't be identical"); |
| 7900 |
} |
7900 |
} |
| 7901 |
return false; |
7901 |
return false; |
| 7902 |
} |
7902 |
} |
| 7903 |
|
7903 |
|
| 7904 |
case ARM::SBFX: |
7904 |
case ARM::SBFX: |
| 7905 |
case ARM::t2SBFX: |
7905 |
case ARM::t2SBFX: |
| 7906 |
case ARM::UBFX: |
7906 |
case ARM::UBFX: |
| 7907 |
case ARM::t2UBFX: { |
7907 |
case ARM::t2UBFX: { |
| 7908 |
// Width must be in range [1, 32-lsb]. |
7908 |
// Width must be in range [1, 32-lsb]. |
| 7909 |
unsigned LSB = Inst.getOperand(2).getImm(); |
7909 |
unsigned LSB = Inst.getOperand(2).getImm(); |
| 7910 |
unsigned Widthm1 = Inst.getOperand(3).getImm(); |
7910 |
unsigned Widthm1 = Inst.getOperand(3).getImm(); |
| 7911 |
if (Widthm1 >= 32 - LSB) |
7911 |
if (Widthm1 >= 32 - LSB) |
| 7912 |
return Error(Operands[5]->getStartLoc(), |
7912 |
return Error(Operands[5]->getStartLoc(), |
| 7913 |
"bitfield width must be in range [1,32-lsb]"); |
7913 |
"bitfield width must be in range [1,32-lsb]"); |
| 7914 |
return false; |
7914 |
return false; |
| 7915 |
} |
7915 |
} |
| 7916 |
// Notionally handles ARM::tLDMIA_UPD too. |
7916 |
// Notionally handles ARM::tLDMIA_UPD too. |
| 7917 |
case ARM::tLDMIA: { |
7917 |
case ARM::tLDMIA: { |
| 7918 |
// If we're parsing Thumb2, the .w variant is available and handles |
7918 |
// If we're parsing Thumb2, the .w variant is available and handles |
| 7919 |
// most cases that are normally illegal for a Thumb1 LDM instruction. |
7919 |
// most cases that are normally illegal for a Thumb1 LDM instruction. |
| 7920 |
// We'll make the transformation in processInstruction() if necessary. |
7920 |
// We'll make the transformation in processInstruction() if necessary. |
| 7921 |
// |
7921 |
// |
| 7922 |
// Thumb LDM instructions are writeback iff the base register is not |
7922 |
// Thumb LDM instructions are writeback iff the base register is not |
| 7923 |
// in the register list. |
7923 |
// in the register list. |
| 7924 |
unsigned Rn = Inst.getOperand(0).getReg(); |
7924 |
unsigned Rn = Inst.getOperand(0).getReg(); |
| 7925 |
bool HasWritebackToken = |
7925 |
bool HasWritebackToken = |
| 7926 |
(static_cast(*Operands[3]).isToken() && |
7926 |
(static_cast(*Operands[3]).isToken() && |
| 7927 |
static_cast(*Operands[3]).getToken() == "!"); |
7927 |
static_cast(*Operands[3]).getToken() == "!"); |
| 7928 |
bool ListContainsBase; |
7928 |
bool ListContainsBase; |
| 7929 |
if (checkLowRegisterList(Inst, 3, Rn, 0, ListContainsBase) && !isThumbTwo()) |
7929 |
if (checkLowRegisterList(Inst, 3, Rn, 0, ListContainsBase) && !isThumbTwo()) |
| 7930 |
return Error(Operands[3 + HasWritebackToken]->getStartLoc(), |
7930 |
return Error(Operands[3 + HasWritebackToken]->getStartLoc(), |
| 7931 |
"registers must be in range r0-r7"); |
7931 |
"registers must be in range r0-r7"); |
| 7932 |
// If we should have writeback, then there should be a '!' token. |
7932 |
// If we should have writeback, then there should be a '!' token. |
| 7933 |
if (!ListContainsBase && !HasWritebackToken && !isThumbTwo()) |
7933 |
if (!ListContainsBase && !HasWritebackToken && !isThumbTwo()) |
| 7934 |
return Error(Operands[2]->getStartLoc(), |
7934 |
return Error(Operands[2]->getStartLoc(), |
| 7935 |
"writeback operator '!' expected"); |
7935 |
"writeback operator '!' expected"); |
| 7936 |
// If we should not have writeback, there must not be a '!'. This is |
7936 |
// If we should not have writeback, there must not be a '!'. This is |
| 7937 |
// true even for the 32-bit wide encodings. |
7937 |
// true even for the 32-bit wide encodings. |
| 7938 |
if (ListContainsBase && HasWritebackToken) |
7938 |
if (ListContainsBase && HasWritebackToken) |
| 7939 |
return Error(Operands[3]->getStartLoc(), |
7939 |
return Error(Operands[3]->getStartLoc(), |
| 7940 |
"writeback operator '!' not allowed when base register " |
7940 |
"writeback operator '!' not allowed when base register " |
| 7941 |
"in register list"); |
7941 |
"in register list"); |
| 7942 |
|
7942 |
|
| 7943 |
if (validatetLDMRegList(Inst, Operands, 3)) |
7943 |
if (validatetLDMRegList(Inst, Operands, 3)) |
| 7944 |
return true; |
7944 |
return true; |
| 7945 |
break; |
7945 |
break; |
| 7946 |
} |
7946 |
} |
| 7947 |
case ARM::LDMIA_UPD: |
7947 |
case ARM::LDMIA_UPD: |
| 7948 |
case ARM::LDMDB_UPD: |
7948 |
case ARM::LDMDB_UPD: |
| 7949 |
case ARM::LDMIB_UPD: |
7949 |
case ARM::LDMIB_UPD: |
| 7950 |
case ARM::LDMDA_UPD: |
7950 |
case ARM::LDMDA_UPD: |
| 7951 |
// ARM variants loading and updating the same register are only officially |
7951 |
// ARM variants loading and updating the same register are only officially |
| 7952 |
// UNPREDICTABLE on v7 upwards. Goodness knows what they did before. |
7952 |
// UNPREDICTABLE on v7 upwards. Goodness knows what they did before. |
| 7953 |
if (!hasV7Ops()) |
7953 |
if (!hasV7Ops()) |
| 7954 |
break; |
7954 |
break; |
| 7955 |
if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg())) |
7955 |
if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg())) |
| 7956 |
return Error(Operands.back()->getStartLoc(), |
7956 |
return Error(Operands.back()->getStartLoc(), |
| 7957 |
"writeback register not allowed in register list"); |
7957 |
"writeback register not allowed in register list"); |
| 7958 |
break; |
7958 |
break; |
| 7959 |
case ARM::t2LDMIA: |
7959 |
case ARM::t2LDMIA: |
| 7960 |
case ARM::t2LDMDB: |
7960 |
case ARM::t2LDMDB: |
| 7961 |
if (validatetLDMRegList(Inst, Operands, 3)) |
7961 |
if (validatetLDMRegList(Inst, Operands, 3)) |
| 7962 |
return true; |
7962 |
return true; |
| 7963 |
break; |
7963 |
break; |
| 7964 |
case ARM::t2STMIA: |
7964 |
case ARM::t2STMIA: |
| 7965 |
case ARM::t2STMDB: |
7965 |
case ARM::t2STMDB: |
| 7966 |
if (validatetSTMRegList(Inst, Operands, 3)) |
7966 |
if (validatetSTMRegList(Inst, Operands, 3)) |
| 7967 |
return true; |
7967 |
return true; |
| 7968 |
break; |
7968 |
break; |
| 7969 |
case ARM::t2LDMIA_UPD: |
7969 |
case ARM::t2LDMIA_UPD: |
| 7970 |
case ARM::t2LDMDB_UPD: |
7970 |
case ARM::t2LDMDB_UPD: |
| 7971 |
case ARM::t2STMIA_UPD: |
7971 |
case ARM::t2STMIA_UPD: |
| 7972 |
case ARM::t2STMDB_UPD: |
7972 |
case ARM::t2STMDB_UPD: |
| 7973 |
if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg())) |
7973 |
if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg())) |
| 7974 |
return Error(Operands.back()->getStartLoc(), |
7974 |
return Error(Operands.back()->getStartLoc(), |
| 7975 |
"writeback register not allowed in register list"); |
7975 |
"writeback register not allowed in register list"); |
| 7976 |
|
7976 |
|
| 7977 |
if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) { |
7977 |
if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) { |
| 7978 |
if (validatetLDMRegList(Inst, Operands, 3)) |
7978 |
if (validatetLDMRegList(Inst, Operands, 3)) |
| 7979 |
return true; |
7979 |
return true; |
| 7980 |
} else { |
7980 |
} else { |
| 7981 |
if (validatetSTMRegList(Inst, Operands, 3)) |
7981 |
if (validatetSTMRegList(Inst, Operands, 3)) |
| 7982 |
return true; |
7982 |
return true; |
| 7983 |
} |
7983 |
} |
| 7984 |
break; |
7984 |
break; |
| 7985 |
|
7985 |
|
| 7986 |
case ARM::sysLDMIA_UPD: |
7986 |
case ARM::sysLDMIA_UPD: |
| 7987 |
case ARM::sysLDMDA_UPD: |
7987 |
case ARM::sysLDMDA_UPD: |
| 7988 |
case ARM::sysLDMDB_UPD: |
7988 |
case ARM::sysLDMDB_UPD: |
| 7989 |
case ARM::sysLDMIB_UPD: |
7989 |
case ARM::sysLDMIB_UPD: |
| 7990 |
if (!listContainsReg(Inst, 3, ARM::PC)) |
7990 |
if (!listContainsReg(Inst, 3, ARM::PC)) |
| 7991 |
return Error(Operands[4]->getStartLoc(), |
7991 |
return Error(Operands[4]->getStartLoc(), |
| 7992 |
"writeback register only allowed on system LDM " |
7992 |
"writeback register only allowed on system LDM " |
| 7993 |
"if PC in register-list"); |
7993 |
"if PC in register-list"); |
| 7994 |
break; |
7994 |
break; |
| 7995 |
case ARM::sysSTMIA_UPD: |
7995 |
case ARM::sysSTMIA_UPD: |
| 7996 |
case ARM::sysSTMDA_UPD: |
7996 |
case ARM::sysSTMDA_UPD: |
| 7997 |
case ARM::sysSTMDB_UPD: |
7997 |
case ARM::sysSTMDB_UPD: |
| 7998 |
case ARM::sysSTMIB_UPD: |
7998 |
case ARM::sysSTMIB_UPD: |
| 7999 |
return Error(Operands[2]->getStartLoc(), |
7999 |
return Error(Operands[2]->getStartLoc(), |
| 8000 |
"system STM cannot have writeback register"); |
8000 |
"system STM cannot have writeback register"); |
| 8001 |
case ARM::tMUL: |
8001 |
case ARM::tMUL: |
| 8002 |
// The second source operand must be the same register as the destination |
8002 |
// The second source operand must be the same register as the destination |
| 8003 |
// operand. |
8003 |
// operand. |
| 8004 |
// |
8004 |
// |
| 8005 |
// In this case, we must directly check the parsed operands because the |
8005 |
// In this case, we must directly check the parsed operands because the |
| 8006 |
// cvtThumbMultiply() function is written in such a way that it guarantees |
8006 |
// cvtThumbMultiply() function is written in such a way that it guarantees |
| 8007 |
// this first statement is always true for the new Inst. Essentially, the |
8007 |
// this first statement is always true for the new Inst. Essentially, the |
| 8008 |
// destination is unconditionally copied into the second source operand |
8008 |
// destination is unconditionally copied into the second source operand |
| 8009 |
// without checking to see if it matches what we actually parsed. |
8009 |
// without checking to see if it matches what we actually parsed. |
| 8010 |
if (Operands.size() == 6 && (((ARMOperand &)*Operands[3]).getReg() != |
8010 |
if (Operands.size() == 6 && (((ARMOperand &)*Operands[3]).getReg() != |
| 8011 |
((ARMOperand &)*Operands[5]).getReg()) && |
8011 |
((ARMOperand &)*Operands[5]).getReg()) && |
| 8012 |
(((ARMOperand &)*Operands[3]).getReg() != |
8012 |
(((ARMOperand &)*Operands[3]).getReg() != |
| 8013 |
((ARMOperand &)*Operands[4]).getReg())) { |
8013 |
((ARMOperand &)*Operands[4]).getReg())) { |
| 8014 |
return Error(Operands[3]->getStartLoc(), |
8014 |
return Error(Operands[3]->getStartLoc(), |
| 8015 |
"destination register must match source register"); |
8015 |
"destination register must match source register"); |
| 8016 |
} |
8016 |
} |
| 8017 |
break; |
8017 |
break; |
| 8018 |
|
8018 |
|
| 8019 |
// Like for ldm/stm, push and pop have hi-reg handling version in Thumb2, |
8019 |
// Like for ldm/stm, push and pop have hi-reg handling version in Thumb2, |
| 8020 |
// so only issue a diagnostic for thumb1. The instructions will be |
8020 |
// so only issue a diagnostic for thumb1. The instructions will be |
| 8021 |
// switched to the t2 encodings in processInstruction() if necessary. |
8021 |
// switched to the t2 encodings in processInstruction() if necessary. |
| 8022 |
case ARM::tPOP: { |
8022 |
case ARM::tPOP: { |
| 8023 |
bool ListContainsBase; |
8023 |
bool ListContainsBase; |
| 8024 |
if (checkLowRegisterList(Inst, 2, 0, ARM::PC, ListContainsBase) && |
8024 |
if (checkLowRegisterList(Inst, 2, 0, ARM::PC, ListContainsBase) && |
| 8025 |
!isThumbTwo()) |
8025 |
!isThumbTwo()) |
| 8026 |
return Error(Operands[2]->getStartLoc(), |
8026 |
return Error(Operands[2]->getStartLoc(), |
| 8027 |
"registers must be in range r0-r7 or pc"); |
8027 |
"registers must be in range r0-r7 or pc"); |
| 8028 |
if (validatetLDMRegList(Inst, Operands, 2, !isMClass())) |
8028 |
if (validatetLDMRegList(Inst, Operands, 2, !isMClass())) |
| 8029 |
return true; |
8029 |
return true; |
| 8030 |
break; |
8030 |
break; |
| 8031 |
} |
8031 |
} |
| 8032 |
case ARM::tPUSH: { |
8032 |
case ARM::tPUSH: { |
| 8033 |
bool ListContainsBase; |
8033 |
bool ListContainsBase; |
| 8034 |
if (checkLowRegisterList(Inst, 2, 0, ARM::LR, ListContainsBase) && |
8034 |
if (checkLowRegisterList(Inst, 2, 0, ARM::LR, ListContainsBase) && |
| 8035 |
!isThumbTwo()) |
8035 |
!isThumbTwo()) |
| 8036 |
return Error(Operands[2]->getStartLoc(), |
8036 |
return Error(Operands[2]->getStartLoc(), |
| 8037 |
"registers must be in range r0-r7 or lr"); |
8037 |
"registers must be in range r0-r7 or lr"); |
| 8038 |
if (validatetSTMRegList(Inst, Operands, 2)) |
8038 |
if (validatetSTMRegList(Inst, Operands, 2)) |
| 8039 |
return true; |
8039 |
return true; |
| 8040 |
break; |
8040 |
break; |
| 8041 |
} |
8041 |
} |
| 8042 |
case ARM::tSTMIA_UPD: { |
8042 |
case ARM::tSTMIA_UPD: { |
| 8043 |
bool ListContainsBase, InvalidLowList; |
8043 |
bool ListContainsBase, InvalidLowList; |
| 8044 |
InvalidLowList = checkLowRegisterList(Inst, 4, Inst.getOperand(0).getReg(), |
8044 |
InvalidLowList = checkLowRegisterList(Inst, 4, Inst.getOperand(0).getReg(), |
| 8045 |
0, ListContainsBase); |
8045 |
0, ListContainsBase); |
| 8046 |
if (InvalidLowList && !isThumbTwo()) |
8046 |
if (InvalidLowList && !isThumbTwo()) |
| 8047 |
return Error(Operands[4]->getStartLoc(), |
8047 |
return Error(Operands[4]->getStartLoc(), |
| 8048 |
"registers must be in range r0-r7"); |
8048 |
"registers must be in range r0-r7"); |
| 8049 |
|
8049 |
|
| 8050 |
// This would be converted to a 32-bit stm, but that's not valid if the |
8050 |
// This would be converted to a 32-bit stm, but that's not valid if the |
| 8051 |
// writeback register is in the list. |
8051 |
// writeback register is in the list. |
| 8052 |
if (InvalidLowList && ListContainsBase) |
8052 |
if (InvalidLowList && ListContainsBase) |
| 8053 |
return Error(Operands[4]->getStartLoc(), |
8053 |
return Error(Operands[4]->getStartLoc(), |
| 8054 |
"writeback operator '!' not allowed when base register " |
8054 |
"writeback operator '!' not allowed when base register " |
| 8055 |
"in register list"); |
8055 |
"in register list"); |
| 8056 |
|
8056 |
|
| 8057 |
if (validatetSTMRegList(Inst, Operands, 4)) |
8057 |
if (validatetSTMRegList(Inst, Operands, 4)) |
| 8058 |
return true; |
8058 |
return true; |
| 8059 |
break; |
8059 |
break; |
| 8060 |
} |
8060 |
} |
| 8061 |
case ARM::tADDrSP: |
8061 |
case ARM::tADDrSP: |
| 8062 |
// If the non-SP source operand and the destination operand are not the |
8062 |
// If the non-SP source operand and the destination operand are not the |
| 8063 |
// same, we need thumb2 (for the wide encoding), or we have an error. |
8063 |
// same, we need thumb2 (for the wide encoding), or we have an error. |
| 8064 |
if (!isThumbTwo() && |
8064 |
if (!isThumbTwo() && |
| 8065 |
Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { |
8065 |
Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { |
| 8066 |
return Error(Operands[4]->getStartLoc(), |
8066 |
return Error(Operands[4]->getStartLoc(), |
| 8067 |
"source register must be the same as destination"); |
8067 |
"source register must be the same as destination"); |
| 8068 |
} |
8068 |
} |
| 8069 |
break; |
8069 |
break; |
| 8070 |
|
8070 |
|
| 8071 |
case ARM::t2ADDrr: |
8071 |
case ARM::t2ADDrr: |
| 8072 |
case ARM::t2ADDrs: |
8072 |
case ARM::t2ADDrs: |
| 8073 |
case ARM::t2SUBrr: |
8073 |
case ARM::t2SUBrr: |
| 8074 |
case ARM::t2SUBrs: |
8074 |
case ARM::t2SUBrs: |
| 8075 |
if (Inst.getOperand(0).getReg() == ARM::SP && |
8075 |
if (Inst.getOperand(0).getReg() == ARM::SP && |
| 8076 |
Inst.getOperand(1).getReg() != ARM::SP) |
8076 |
Inst.getOperand(1).getReg() != ARM::SP) |
| 8077 |
return Error(Operands[4]->getStartLoc(), |
8077 |
return Error(Operands[4]->getStartLoc(), |
| 8078 |
"source register must be sp if destination is sp"); |
8078 |
"source register must be sp if destination is sp"); |
| 8079 |
break; |
8079 |
break; |
| 8080 |
|
8080 |
|
| 8081 |
// Final range checking for Thumb unconditional branch instructions. |
8081 |
// Final range checking for Thumb unconditional branch instructions. |
| 8082 |
case ARM::tB: |
8082 |
case ARM::tB: |
| 8083 |
if (!(static_cast(*Operands[2])).isSignedOffset<11, 1>()) |
8083 |
if (!(static_cast(*Operands[2])).isSignedOffset<11, 1>()) |
| 8084 |
return Error(Operands[2]->getStartLoc(), "branch target out of range"); |
8084 |
return Error(Operands[2]->getStartLoc(), "branch target out of range"); |
| 8085 |
break; |
8085 |
break; |
| 8086 |
case ARM::t2B: { |
8086 |
case ARM::t2B: { |
| 8087 |
int op = (Operands[2]->isImm()) ? 2 : 3; |
8087 |
int op = (Operands[2]->isImm()) ? 2 : 3; |
| 8088 |
ARMOperand &Operand = static_cast(*Operands[op]); |
8088 |
ARMOperand &Operand = static_cast(*Operands[op]); |
| 8089 |
// Delay the checks of symbolic expressions until they are resolved. |
8089 |
// Delay the checks of symbolic expressions until they are resolved. |
| 8090 |
if (!isa(Operand.getImm()) && |
8090 |
if (!isa(Operand.getImm()) && |
| 8091 |
!Operand.isSignedOffset<24, 1>()) |
8091 |
!Operand.isSignedOffset<24, 1>()) |
| 8092 |
return Error(Operands[op]->getStartLoc(), "branch target out of range"); |
8092 |
return Error(Operands[op]->getStartLoc(), "branch target out of range"); |
| 8093 |
break; |
8093 |
break; |
| 8094 |
} |
8094 |
} |
| 8095 |
// Final range checking for Thumb conditional branch instructions. |
8095 |
// Final range checking for Thumb conditional branch instructions. |
| 8096 |
case ARM::tBcc: |
8096 |
case ARM::tBcc: |
| 8097 |
if (!static_cast(*Operands[2]).isSignedOffset<8, 1>()) |
8097 |
if (!static_cast(*Operands[2]).isSignedOffset<8, 1>()) |
| 8098 |
return Error(Operands[2]->getStartLoc(), "branch target out of range"); |
8098 |
return Error(Operands[2]->getStartLoc(), "branch target out of range"); |
| 8099 |
break; |
8099 |
break; |
| 8100 |
case ARM::t2Bcc: { |
8100 |
case ARM::t2Bcc: { |
| 8101 |
int Op = (Operands[2]->isImm()) ? 2 : 3; |
8101 |
int Op = (Operands[2]->isImm()) ? 2 : 3; |
| 8102 |
if (!static_cast(*Operands[Op]).isSignedOffset<20, 1>()) |
8102 |
if (!static_cast(*Operands[Op]).isSignedOffset<20, 1>()) |
| 8103 |
return Error(Operands[Op]->getStartLoc(), "branch target out of range"); |
8103 |
return Error(Operands[Op]->getStartLoc(), "branch target out of range"); |
| 8104 |
break; |
8104 |
break; |
| 8105 |
} |
8105 |
} |
| 8106 |
case ARM::tCBZ: |
8106 |
case ARM::tCBZ: |
| 8107 |
case ARM::tCBNZ: { |
8107 |
case ARM::tCBNZ: { |
| 8108 |
if (!static_cast(*Operands[2]).isUnsignedOffset<6, 1>()) |
8108 |
if (!static_cast(*Operands[2]).isUnsignedOffset<6, 1>()) |
| 8109 |
return Error(Operands[2]->getStartLoc(), "branch target out of range"); |
8109 |
return Error(Operands[2]->getStartLoc(), "branch target out of range"); |
| 8110 |
break; |
8110 |
break; |
| 8111 |
} |
8111 |
} |
| 8112 |
case ARM::MOVi16: |
8112 |
case ARM::MOVi16: |
| 8113 |
case ARM::MOVTi16: |
8113 |
case ARM::MOVTi16: |
| 8114 |
case ARM::t2MOVi16: |
8114 |
case ARM::t2MOVi16: |
| 8115 |
case ARM::t2MOVTi16: |
8115 |
case ARM::t2MOVTi16: |
| 8116 |
{ |
8116 |
{ |
| 8117 |
// We want to avoid misleadingly allowing something like "mov r0, " |
8117 |
// We want to avoid misleadingly allowing something like "mov r0, " |
| 8118 |
// especially when we turn it into a movw and the expression does |
8118 |
// especially when we turn it into a movw and the expression does |
| 8119 |
// not have a :lower16: or :upper16 as part of the expression. We don't |
8119 |
// not have a :lower16: or :upper16 as part of the expression. We don't |
| 8120 |
// want the behavior of silently truncating, which can be unexpected and |
8120 |
// want the behavior of silently truncating, which can be unexpected and |
| 8121 |
// lead to bugs that are difficult to find since this is an easy mistake |
8121 |
// lead to bugs that are difficult to find since this is an easy mistake |
| 8122 |
// to make. |
8122 |
// to make. |
| 8123 |
int i = (Operands[3]->isImm()) ? 3 : 4; |
8123 |
int i = (Operands[3]->isImm()) ? 3 : 4; |
| 8124 |
ARMOperand &Op = static_cast(*Operands[i]); |
8124 |
ARMOperand &Op = static_cast(*Operands[i]); |
| 8125 |
const MCConstantExpr *CE = dyn_cast(Op.getImm()); |
8125 |
const MCConstantExpr *CE = dyn_cast(Op.getImm()); |
| 8126 |
if (CE) break; |
8126 |
if (CE) break; |
| 8127 |
const MCExpr *E = dyn_cast(Op.getImm()); |
8127 |
const MCExpr *E = dyn_cast(Op.getImm()); |
| 8128 |
if (!E) break; |
8128 |
if (!E) break; |
| 8129 |
const ARMMCExpr *ARM16Expr = dyn_cast(E); |
8129 |
const ARMMCExpr *ARM16Expr = dyn_cast(E); |
| 8130 |
if (!ARM16Expr || (ARM16Expr->getKind() != ARMMCExpr::VK_ARM_HI16 && |
8130 |
if (!ARM16Expr || (ARM16Expr->getKind() != ARMMCExpr::VK_ARM_HI16 && |
| 8131 |
ARM16Expr->getKind() != ARMMCExpr::VK_ARM_LO16)) |
8131 |
ARM16Expr->getKind() != ARMMCExpr::VK_ARM_LO16)) |
| 8132 |
return Error( |
8132 |
return Error( |
| 8133 |
Op.getStartLoc(), |
8133 |
Op.getStartLoc(), |
| 8134 |
"immediate expression for mov requires :lower16: or :upper16"); |
8134 |
"immediate expression for mov requires :lower16: or :upper16"); |
| 8135 |
break; |
8135 |
break; |
| 8136 |
} |
8136 |
} |
| 8137 |
case ARM::tADDi8: { |
8137 |
case ARM::tADDi8: { |
| 8138 |
MCParsedAsmOperand &Op = *Operands[4]; |
8138 |
MCParsedAsmOperand &Op = *Operands[4]; |
| 8139 |
if (isARMMCExpr(Op) && !isThumbI8Relocation(Op)) |
8139 |
if (isARMMCExpr(Op) && !isThumbI8Relocation(Op)) |
| 8140 |
return Error(Op.getStartLoc(), |
8140 |
return Error(Op.getStartLoc(), |
| 8141 |
"Immediate expression for Thumb adds requires :lower0_7:," |
8141 |
"Immediate expression for Thumb adds requires :lower0_7:," |
| 8142 |
" :lower8_15:, :upper0_7: or :upper8_15:"); |
8142 |
" :lower8_15:, :upper0_7: or :upper8_15:"); |
| 8143 |
break; |
8143 |
break; |
| 8144 |
} |
8144 |
} |
| 8145 |
case ARM::tMOVi8: { |
8145 |
case ARM::tMOVi8: { |
| 8146 |
MCParsedAsmOperand &Op = *Operands[2]; |
8146 |
MCParsedAsmOperand &Op = *Operands[2]; |
| 8147 |
if (isARMMCExpr(Op) && !isThumbI8Relocation(Op)) |
8147 |
if (isARMMCExpr(Op) && !isThumbI8Relocation(Op)) |
| 8148 |
return Error(Op.getStartLoc(), |
8148 |
return Error(Op.getStartLoc(), |
| 8149 |
"Immediate expression for Thumb movs requires :lower0_7:," |
8149 |
"Immediate expression for Thumb movs requires :lower0_7:," |
| 8150 |
" :lower8_15:, :upper0_7: or :upper8_15:"); |
8150 |
" :lower8_15:, :upper0_7: or :upper8_15:"); |
| 8151 |
break; |
8151 |
break; |
| 8152 |
} |
8152 |
} |
| 8153 |
case ARM::HINT: |
8153 |
case ARM::HINT: |
| 8154 |
case ARM::t2HINT: { |
8154 |
case ARM::t2HINT: { |
| 8155 |
unsigned Imm8 = Inst.getOperand(0).getImm(); |
8155 |
unsigned Imm8 = Inst.getOperand(0).getImm(); |
| 8156 |
unsigned Pred = Inst.getOperand(1).getImm(); |
8156 |
unsigned Pred = Inst.getOperand(1).getImm(); |
| 8157 |
// ESB is not predicable (pred must be AL). Without the RAS extension, this |
8157 |
// ESB is not predicable (pred must be AL). Without the RAS extension, this |
| 8158 |
// behaves as any other unallocated hint. |
8158 |
// behaves as any other unallocated hint. |
| 8159 |
if (Imm8 == 0x10 && Pred != ARMCC::AL && hasRAS()) |
8159 |
if (Imm8 == 0x10 && Pred != ARMCC::AL && hasRAS()) |
| 8160 |
return Error(Operands[1]->getStartLoc(), "instruction 'esb' is not " |
8160 |
return Error(Operands[1]->getStartLoc(), "instruction 'esb' is not " |
| 8161 |
"predicable, but condition " |
8161 |
"predicable, but condition " |
| 8162 |
"code specified"); |
8162 |
"code specified"); |
| 8163 |
if (Imm8 == 0x14 && Pred != ARMCC::AL) |
8163 |
if (Imm8 == 0x14 && Pred != ARMCC::AL) |
| 8164 |
return Error(Operands[1]->getStartLoc(), "instruction 'csdb' is not " |
8164 |
return Error(Operands[1]->getStartLoc(), "instruction 'csdb' is not " |
| 8165 |
"predicable, but condition " |
8165 |
"predicable, but condition " |
| 8166 |
"code specified"); |
8166 |
"code specified"); |
| 8167 |
break; |
8167 |
break; |
| 8168 |
} |
8168 |
} |
| 8169 |
case ARM::t2BFi: |
8169 |
case ARM::t2BFi: |
| 8170 |
case ARM::t2BFr: |
8170 |
case ARM::t2BFr: |
| 8171 |
case ARM::t2BFLi: |
8171 |
case ARM::t2BFLi: |
| 8172 |
case ARM::t2BFLr: { |
8172 |
case ARM::t2BFLr: { |
| 8173 |
if (!static_cast(*Operands[2]).isUnsignedOffset<4, 1>() || |
8173 |
if (!static_cast(*Operands[2]).isUnsignedOffset<4, 1>() || |
| 8174 |
(Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0)) |
8174 |
(Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0)) |
| 8175 |
return Error(Operands[2]->getStartLoc(), |
8175 |
return Error(Operands[2]->getStartLoc(), |
| 8176 |
"branch location out of range or not a multiple of 2"); |
8176 |
"branch location out of range or not a multiple of 2"); |
| 8177 |
|
8177 |
|
| 8178 |
if (Opcode == ARM::t2BFi) { |
8178 |
if (Opcode == ARM::t2BFi) { |
| 8179 |
if (!static_cast(*Operands[3]).isSignedOffset<16, 1>()) |
8179 |
if (!static_cast(*Operands[3]).isSignedOffset<16, 1>()) |
| 8180 |
return Error(Operands[3]->getStartLoc(), |
8180 |
return Error(Operands[3]->getStartLoc(), |
| 8181 |
"branch target out of range or not a multiple of 2"); |
8181 |
"branch target out of range or not a multiple of 2"); |
| 8182 |
} else if (Opcode == ARM::t2BFLi) { |
8182 |
} else if (Opcode == ARM::t2BFLi) { |
| 8183 |
if (!static_cast(*Operands[3]).isSignedOffset<18, 1>()) |
8183 |
if (!static_cast(*Operands[3]).isSignedOffset<18, 1>()) |
| 8184 |
return Error(Operands[3]->getStartLoc(), |
8184 |
return Error(Operands[3]->getStartLoc(), |
| 8185 |
"branch target out of range or not a multiple of 2"); |
8185 |
"branch target out of range or not a multiple of 2"); |
| 8186 |
} |
8186 |
} |
| 8187 |
break; |
8187 |
break; |
| 8188 |
} |
8188 |
} |
| 8189 |
case ARM::t2BFic: { |
8189 |
case ARM::t2BFic: { |
| 8190 |
if (!static_cast(*Operands[1]).isUnsignedOffset<4, 1>() || |
8190 |
if (!static_cast(*Operands[1]).isUnsignedOffset<4, 1>() || |
| 8191 |
(Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0)) |
8191 |
(Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0)) |
| 8192 |
return Error(Operands[1]->getStartLoc(), |
8192 |
return Error(Operands[1]->getStartLoc(), |
| 8193 |
"branch location out of range or not a multiple of 2"); |
8193 |
"branch location out of range or not a multiple of 2"); |
| 8194 |
|
8194 |
|
| 8195 |
if (!static_cast(*Operands[2]).isSignedOffset<16, 1>()) |
8195 |
if (!static_cast(*Operands[2]).isSignedOffset<16, 1>()) |
| 8196 |
return Error(Operands[2]->getStartLoc(), |
8196 |
return Error(Operands[2]->getStartLoc(), |
| 8197 |
"branch target out of range or not a multiple of 2"); |
8197 |
"branch target out of range or not a multiple of 2"); |
| 8198 |
|
8198 |
|
| 8199 |
assert(Inst.getOperand(0).isImm() == Inst.getOperand(2).isImm() && |
8199 |
assert(Inst.getOperand(0).isImm() == Inst.getOperand(2).isImm() && |
| 8200 |
"branch location and else branch target should either both be " |
8200 |
"branch location and else branch target should either both be " |
| 8201 |
"immediates or both labels"); |
8201 |
"immediates or both labels"); |
| 8202 |
|
8202 |
|
| 8203 |
if (Inst.getOperand(0).isImm() && Inst.getOperand(2).isImm()) { |
8203 |
if (Inst.getOperand(0).isImm() && Inst.getOperand(2).isImm()) { |
| 8204 |
int Diff = Inst.getOperand(2).getImm() - Inst.getOperand(0).getImm(); |
8204 |
int Diff = Inst.getOperand(2).getImm() - Inst.getOperand(0).getImm(); |
| 8205 |
if (Diff != 4 && Diff != 2) |
8205 |
if (Diff != 4 && Diff != 2) |
| 8206 |
return Error( |
8206 |
return Error( |
| 8207 |
Operands[3]->getStartLoc(), |
8207 |
Operands[3]->getStartLoc(), |
| 8208 |
"else branch target must be 2 or 4 greater than the branch location"); |
8208 |
"else branch target must be 2 or 4 greater than the branch location"); |
| 8209 |
} |
8209 |
} |
| 8210 |
break; |
8210 |
break; |
| 8211 |
} |
8211 |
} |
| 8212 |
case ARM::t2CLRM: { |
8212 |
case ARM::t2CLRM: { |
| 8213 |
for (unsigned i = 2; i < Inst.getNumOperands(); i++) { |
8213 |
for (unsigned i = 2; i < Inst.getNumOperands(); i++) { |
| 8214 |
if (Inst.getOperand(i).isReg() && |
8214 |
if (Inst.getOperand(i).isReg() && |
| 8215 |
!ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains( |
8215 |
!ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains( |
| 8216 |
Inst.getOperand(i).getReg())) { |
8216 |
Inst.getOperand(i).getReg())) { |
| 8217 |
return Error(Operands[2]->getStartLoc(), |
8217 |
return Error(Operands[2]->getStartLoc(), |
| 8218 |
"invalid register in register list. Valid registers are " |
8218 |
"invalid register in register list. Valid registers are " |
| 8219 |
"r0-r12, lr/r14 and APSR."); |
8219 |
"r0-r12, lr/r14 and APSR."); |
| 8220 |
} |
8220 |
} |
| 8221 |
} |
8221 |
} |
| 8222 |
break; |
8222 |
break; |
| 8223 |
} |
8223 |
} |
| 8224 |
case ARM::DSB: |
8224 |
case ARM::DSB: |
| 8225 |
case ARM::t2DSB: { |
8225 |
case ARM::t2DSB: { |
| 8226 |
|
8226 |
|
| 8227 |
if (Inst.getNumOperands() < 2) |
8227 |
if (Inst.getNumOperands() < 2) |
| 8228 |
break; |
8228 |
break; |
| 8229 |
|
8229 |
|
| 8230 |
unsigned Option = Inst.getOperand(0).getImm(); |
8230 |
unsigned Option = Inst.getOperand(0).getImm(); |
| 8231 |
unsigned Pred = Inst.getOperand(1).getImm(); |
8231 |
unsigned Pred = Inst.getOperand(1).getImm(); |
| 8232 |
|
8232 |
|
| 8233 |
// SSBB and PSSBB (DSB #0|#4) are not predicable (pred must be AL). |
8233 |
// SSBB and PSSBB (DSB #0|#4) are not predicable (pred must be AL). |
| 8234 |
if (Option == 0 && Pred != ARMCC::AL) |
8234 |
if (Option == 0 && Pred != ARMCC::AL) |
| 8235 |
return Error(Operands[1]->getStartLoc(), |
8235 |
return Error(Operands[1]->getStartLoc(), |
| 8236 |
"instruction 'ssbb' is not predicable, but condition code " |
8236 |
"instruction 'ssbb' is not predicable, but condition code " |
| 8237 |
"specified"); |
8237 |
"specified"); |
| 8238 |
if (Option == 4 && Pred != ARMCC::AL) |
8238 |
if (Option == 4 && Pred != ARMCC::AL) |
| 8239 |
return Error(Operands[1]->getStartLoc(), |
8239 |
return Error(Operands[1]->getStartLoc(), |
| 8240 |
"instruction 'pssbb' is not predicable, but condition code " |
8240 |
"instruction 'pssbb' is not predicable, but condition code " |
| 8241 |
"specified"); |
8241 |
"specified"); |
| 8242 |
break; |
8242 |
break; |
| 8243 |
} |
8243 |
} |
| 8244 |
case ARM::VMOVRRS: { |
8244 |
case ARM::VMOVRRS: { |
| 8245 |
// Source registers must be sequential. |
8245 |
// Source registers must be sequential. |
| 8246 |
const unsigned Sm = MRI->getEncodingValue(Inst.getOperand(2).getReg()); |
8246 |
const unsigned Sm = MRI->getEncodingValue(Inst.getOperand(2).getReg()); |
| 8247 |
const unsigned Sm1 = MRI->getEncodingValue(Inst.getOperand(3).getReg()); |
8247 |
const unsigned Sm1 = MRI->getEncodingValue(Inst.getOperand(3).getReg()); |
| 8248 |
if (Sm1 != Sm + 1) |
8248 |
if (Sm1 != Sm + 1) |
| 8249 |
return Error(Operands[5]->getStartLoc(), |
8249 |
return Error(Operands[5]->getStartLoc(), |
| 8250 |
"source operands must be sequential"); |
8250 |
"source operands must be sequential"); |
| 8251 |
break; |
8251 |
break; |
| 8252 |
} |
8252 |
} |
| 8253 |
case ARM::VMOVSRR: { |
8253 |
case ARM::VMOVSRR: { |
| 8254 |
// Destination registers must be sequential. |
8254 |
// Destination registers must be sequential. |
| 8255 |
const unsigned Sm = MRI->getEncodingValue(Inst.getOperand(0).getReg()); |
8255 |
const unsigned Sm = MRI->getEncodingValue(Inst.getOperand(0).getReg()); |
| 8256 |
const unsigned Sm1 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); |
8256 |
const unsigned Sm1 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); |
| 8257 |
if (Sm1 != Sm + 1) |
8257 |
if (Sm1 != Sm + 1) |
| 8258 |
return Error(Operands[3]->getStartLoc(), |
8258 |
return Error(Operands[3]->getStartLoc(), |
| 8259 |
"destination operands must be sequential"); |
8259 |
"destination operands must be sequential"); |
| 8260 |
break; |
8260 |
break; |
| 8261 |
} |
8261 |
} |
| 8262 |
case ARM::VLDMDIA: |
8262 |
case ARM::VLDMDIA: |
| 8263 |
case ARM::VSTMDIA: { |
8263 |
case ARM::VSTMDIA: { |
| 8264 |
ARMOperand &Op = static_cast(*Operands[3]); |
8264 |
ARMOperand &Op = static_cast(*Operands[3]); |
| 8265 |
auto &RegList = Op.getRegList(); |
8265 |
auto &RegList = Op.getRegList(); |
| 8266 |
if (RegList.size() < 1 || RegList.size() > 16) |
8266 |
if (RegList.size() < 1 || RegList.size() > 16) |
| 8267 |
return Error(Operands[3]->getStartLoc(), |
8267 |
return Error(Operands[3]->getStartLoc(), |
| 8268 |
"list of registers must be at least 1 and at most 16"); |
8268 |
"list of registers must be at least 1 and at most 16"); |
| 8269 |
break; |
8269 |
break; |
| 8270 |
} |
8270 |
} |
| 8271 |
case ARM::MVE_VQDMULLs32bh: |
8271 |
case ARM::MVE_VQDMULLs32bh: |
| 8272 |
case ARM::MVE_VQDMULLs32th: |
8272 |
case ARM::MVE_VQDMULLs32th: |
| 8273 |
case ARM::MVE_VCMULf32: |
8273 |
case ARM::MVE_VCMULf32: |
| 8274 |
case ARM::MVE_VMULLBs32: |
8274 |
case ARM::MVE_VMULLBs32: |
| 8275 |
case ARM::MVE_VMULLTs32: |
8275 |
case ARM::MVE_VMULLTs32: |
| 8276 |
case ARM::MVE_VMULLBu32: |
8276 |
case ARM::MVE_VMULLBu32: |
| 8277 |
case ARM::MVE_VMULLTu32: { |
8277 |
case ARM::MVE_VMULLTu32: { |
| 8278 |
if (Operands[3]->getReg() == Operands[4]->getReg()) { |
8278 |
if (Operands[3]->getReg() == Operands[4]->getReg()) { |
| 8279 |
return Error (Operands[3]->getStartLoc(), |
8279 |
return Error (Operands[3]->getStartLoc(), |
| 8280 |
"Qd register and Qn register can't be identical"); |
8280 |
"Qd register and Qn register can't be identical"); |
| 8281 |
} |
8281 |
} |
| 8282 |
if (Operands[3]->getReg() == Operands[5]->getReg()) { |
8282 |
if (Operands[3]->getReg() == Operands[5]->getReg()) { |
| 8283 |
return Error (Operands[3]->getStartLoc(), |
8283 |
return Error (Operands[3]->getStartLoc(), |
| 8284 |
"Qd register and Qm register can't be identical"); |
8284 |
"Qd register and Qm register can't be identical"); |
| 8285 |
} |
8285 |
} |
| 8286 |
break; |
8286 |
break; |
| 8287 |
} |
8287 |
} |
| 8288 |
case ARM::MVE_VREV64_8: |
8288 |
case ARM::MVE_VREV64_8: |
| 8289 |
case ARM::MVE_VREV64_16: |
8289 |
case ARM::MVE_VREV64_16: |
| 8290 |
case ARM::MVE_VREV64_32: |
8290 |
case ARM::MVE_VREV64_32: |
| 8291 |
case ARM::MVE_VQDMULL_qr_s32bh: |
8291 |
case ARM::MVE_VQDMULL_qr_s32bh: |
| 8292 |
case ARM::MVE_VQDMULL_qr_s32th: { |
8292 |
case ARM::MVE_VQDMULL_qr_s32th: { |
| 8293 |
if (Operands[3]->getReg() == Operands[4]->getReg()) { |
8293 |
if (Operands[3]->getReg() == Operands[4]->getReg()) { |
| 8294 |
return Error (Operands[3]->getStartLoc(), |
8294 |
return Error (Operands[3]->getStartLoc(), |
| 8295 |
"Qd register and Qn register can't be identical"); |
8295 |
"Qd register and Qn register can't be identical"); |
| 8296 |
} |
8296 |
} |
| 8297 |
break; |
8297 |
break; |
| 8298 |
} |
8298 |
} |
| 8299 |
case ARM::MVE_VCADDi32: |
8299 |
case ARM::MVE_VCADDi32: |
| 8300 |
case ARM::MVE_VCADDf32: |
8300 |
case ARM::MVE_VCADDf32: |
| 8301 |
case ARM::MVE_VHCADDs32: { |
8301 |
case ARM::MVE_VHCADDs32: { |
| 8302 |
if (Operands[3]->getReg() == Operands[5]->getReg()) { |
8302 |
if (Operands[3]->getReg() == Operands[5]->getReg()) { |
| 8303 |
return Error (Operands[3]->getStartLoc(), |
8303 |
return Error (Operands[3]->getStartLoc(), |
| 8304 |
"Qd register and Qm register can't be identical"); |
8304 |
"Qd register and Qm register can't be identical"); |
| 8305 |
} |
8305 |
} |
| 8306 |
break; |
8306 |
break; |
| 8307 |
} |
8307 |
} |
| 8308 |
case ARM::MVE_VMOV_rr_q: { |
8308 |
case ARM::MVE_VMOV_rr_q: { |
| 8309 |
if (Operands[4]->getReg() != Operands[6]->getReg()) |
8309 |
if (Operands[4]->getReg() != Operands[6]->getReg()) |
| 8310 |
return Error (Operands[4]->getStartLoc(), "Q-registers must be the same"); |
8310 |
return Error (Operands[4]->getStartLoc(), "Q-registers must be the same"); |
| 8311 |
if (static_cast(*Operands[5]).getVectorIndex() != |
8311 |
if (static_cast(*Operands[5]).getVectorIndex() != |
| 8312 |
static_cast(*Operands[7]).getVectorIndex() + 2) |
8312 |
static_cast(*Operands[7]).getVectorIndex() + 2) |
| 8313 |
return Error (Operands[5]->getStartLoc(), "Q-register indexes must be 2 and 0 or 3 and 1"); |
8313 |
return Error (Operands[5]->getStartLoc(), "Q-register indexes must be 2 and 0 or 3 and 1"); |
| 8314 |
break; |
8314 |
break; |
| 8315 |
} |
8315 |
} |
| 8316 |
case ARM::MVE_VMOV_q_rr: { |
8316 |
case ARM::MVE_VMOV_q_rr: { |
| 8317 |
if (Operands[2]->getReg() != Operands[4]->getReg()) |
8317 |
if (Operands[2]->getReg() != Operands[4]->getReg()) |
| 8318 |
return Error (Operands[2]->getStartLoc(), "Q-registers must be the same"); |
8318 |
return Error (Operands[2]->getStartLoc(), "Q-registers must be the same"); |
| 8319 |
if (static_cast(*Operands[3]).getVectorIndex() != |
8319 |
if (static_cast(*Operands[3]).getVectorIndex() != |
| 8320 |
static_cast(*Operands[5]).getVectorIndex() + 2) |
8320 |
static_cast(*Operands[5]).getVectorIndex() + 2) |
| 8321 |
return Error (Operands[3]->getStartLoc(), "Q-register indexes must be 2 and 0 or 3 and 1"); |
8321 |
return Error (Operands[3]->getStartLoc(), "Q-register indexes must be 2 and 0 or 3 and 1"); |
| 8322 |
break; |
8322 |
break; |
| 8323 |
} |
8323 |
} |
| 8324 |
case ARM::UMAAL: |
8324 |
case ARM::UMAAL: |
| 8325 |
case ARM::UMLAL: |
8325 |
case ARM::UMLAL: |
| 8326 |
case ARM::UMULL: |
8326 |
case ARM::UMULL: |
| 8327 |
case ARM::t2UMAAL: |
8327 |
case ARM::t2UMAAL: |
| 8328 |
case ARM::t2UMLAL: |
8328 |
case ARM::t2UMLAL: |
| 8329 |
case ARM::t2UMULL: |
8329 |
case ARM::t2UMULL: |
| 8330 |
case ARM::SMLAL: |
8330 |
case ARM::SMLAL: |
| 8331 |
case ARM::SMLALBB: |
8331 |
case ARM::SMLALBB: |
| 8332 |
case ARM::SMLALBT: |
8332 |
case ARM::SMLALBT: |
| 8333 |
case ARM::SMLALD: |
8333 |
case ARM::SMLALD: |
| 8334 |
case ARM::SMLALDX: |
8334 |
case ARM::SMLALDX: |
| 8335 |
case ARM::SMLALTB: |
8335 |
case ARM::SMLALTB: |
| 8336 |
case ARM::SMLALTT: |
8336 |
case ARM::SMLALTT: |
| 8337 |
case ARM::SMLSLD: |
8337 |
case ARM::SMLSLD: |
| 8338 |
case ARM::SMLSLDX: |
8338 |
case ARM::SMLSLDX: |
| 8339 |
case ARM::SMULL: |
8339 |
case ARM::SMULL: |
| 8340 |
case ARM::t2SMLAL: |
8340 |
case ARM::t2SMLAL: |
| 8341 |
case ARM::t2SMLALBB: |
8341 |
case ARM::t2SMLALBB: |
| 8342 |
case ARM::t2SMLALBT: |
8342 |
case ARM::t2SMLALBT: |
| 8343 |
case ARM::t2SMLALD: |
8343 |
case ARM::t2SMLALD: |
| 8344 |
case ARM::t2SMLALDX: |
8344 |
case ARM::t2SMLALDX: |
| 8345 |
case ARM::t2SMLALTB: |
8345 |
case ARM::t2SMLALTB: |
| 8346 |
case ARM::t2SMLALTT: |
8346 |
case ARM::t2SMLALTT: |
| 8347 |
case ARM::t2SMLSLD: |
8347 |
case ARM::t2SMLSLD: |
| 8348 |
case ARM::t2SMLSLDX: |
8348 |
case ARM::t2SMLSLDX: |
| 8349 |
case ARM::t2SMULL: { |
8349 |
case ARM::t2SMULL: { |
| 8350 |
unsigned RdHi = Inst.getOperand(0).getReg(); |
8350 |
unsigned RdHi = Inst.getOperand(0).getReg(); |
| 8351 |
unsigned RdLo = Inst.getOperand(1).getReg(); |
8351 |
unsigned RdLo = Inst.getOperand(1).getReg(); |
| 8352 |
if(RdHi == RdLo) { |
8352 |
if(RdHi == RdLo) { |
| 8353 |
return Error(Loc, |
8353 |
return Error(Loc, |
| 8354 |
"unpredictable instruction, RdHi and RdLo must be different"); |
8354 |
"unpredictable instruction, RdHi and RdLo must be different"); |
| 8355 |
} |
8355 |
} |
| 8356 |
break; |
8356 |
break; |
| 8357 |
} |
8357 |
} |
| 8358 |
|
8358 |
|
| 8359 |
case ARM::CDE_CX1: |
8359 |
case ARM::CDE_CX1: |
| 8360 |
case ARM::CDE_CX1A: |
8360 |
case ARM::CDE_CX1A: |
| 8361 |
case ARM::CDE_CX1D: |
8361 |
case ARM::CDE_CX1D: |
| 8362 |
case ARM::CDE_CX1DA: |
8362 |
case ARM::CDE_CX1DA: |
| 8363 |
case ARM::CDE_CX2: |
8363 |
case ARM::CDE_CX2: |
| 8364 |
case ARM::CDE_CX2A: |
8364 |
case ARM::CDE_CX2A: |
| 8365 |
case ARM::CDE_CX2D: |
8365 |
case ARM::CDE_CX2D: |
| 8366 |
case ARM::CDE_CX2DA: |
8366 |
case ARM::CDE_CX2DA: |
| 8367 |
case ARM::CDE_CX3: |
8367 |
case ARM::CDE_CX3: |
| 8368 |
case ARM::CDE_CX3A: |
8368 |
case ARM::CDE_CX3A: |
| 8369 |
case ARM::CDE_CX3D: |
8369 |
case ARM::CDE_CX3D: |
| 8370 |
case ARM::CDE_CX3DA: |
8370 |
case ARM::CDE_CX3DA: |
| 8371 |
case ARM::CDE_VCX1_vec: |
8371 |
case ARM::CDE_VCX1_vec: |
| 8372 |
case ARM::CDE_VCX1_fpsp: |
8372 |
case ARM::CDE_VCX1_fpsp: |
| 8373 |
case ARM::CDE_VCX1_fpdp: |
8373 |
case ARM::CDE_VCX1_fpdp: |
| 8374 |
case ARM::CDE_VCX1A_vec: |
8374 |
case ARM::CDE_VCX1A_vec: |
| 8375 |
case ARM::CDE_VCX1A_fpsp: |
8375 |
case ARM::CDE_VCX1A_fpsp: |
| 8376 |
case ARM::CDE_VCX1A_fpdp: |
8376 |
case ARM::CDE_VCX1A_fpdp: |
| 8377 |
case ARM::CDE_VCX2_vec: |
8377 |
case ARM::CDE_VCX2_vec: |
| 8378 |
case ARM::CDE_VCX2_fpsp: |
8378 |
case ARM::CDE_VCX2_fpsp: |
| 8379 |
case ARM::CDE_VCX2_fpdp: |
8379 |
case ARM::CDE_VCX2_fpdp: |
| 8380 |
case ARM::CDE_VCX2A_vec: |
8380 |
case ARM::CDE_VCX2A_vec: |
| 8381 |
case ARM::CDE_VCX2A_fpsp: |
8381 |
case ARM::CDE_VCX2A_fpsp: |
| 8382 |
case ARM::CDE_VCX2A_fpdp: |
8382 |
case ARM::CDE_VCX2A_fpdp: |
| 8383 |
case ARM::CDE_VCX3_vec: |
8383 |
case ARM::CDE_VCX3_vec: |
| 8384 |
case ARM::CDE_VCX3_fpsp: |
8384 |
case ARM::CDE_VCX3_fpsp: |
| 8385 |
case ARM::CDE_VCX3_fpdp: |
8385 |
case ARM::CDE_VCX3_fpdp: |
| 8386 |
case ARM::CDE_VCX3A_vec: |
8386 |
case ARM::CDE_VCX3A_vec: |
| 8387 |
case ARM::CDE_VCX3A_fpsp: |
8387 |
case ARM::CDE_VCX3A_fpsp: |
| 8388 |
case ARM::CDE_VCX3A_fpdp: { |
8388 |
case ARM::CDE_VCX3A_fpdp: { |
| 8389 |
assert(Inst.getOperand(1).isImm() && |
8389 |
assert(Inst.getOperand(1).isImm() && |
| 8390 |
"CDE operand 1 must be a coprocessor ID"); |
8390 |
"CDE operand 1 must be a coprocessor ID"); |
| 8391 |
int64_t Coproc = Inst.getOperand(1).getImm(); |
8391 |
int64_t Coproc = Inst.getOperand(1).getImm(); |
| 8392 |
if (Coproc < 8 && !ARM::isCDECoproc(Coproc, *STI)) |
8392 |
if (Coproc < 8 && !ARM::isCDECoproc(Coproc, *STI)) |
| 8393 |
return Error(Operands[1]->getStartLoc(), |
8393 |
return Error(Operands[1]->getStartLoc(), |
| 8394 |
"coprocessor must be configured as CDE"); |
8394 |
"coprocessor must be configured as CDE"); |
| 8395 |
else if (Coproc >= 8) |
8395 |
else if (Coproc >= 8) |
| 8396 |
return Error(Operands[1]->getStartLoc(), |
8396 |
return Error(Operands[1]->getStartLoc(), |
| 8397 |
"coprocessor must be in the range [p0, p7]"); |
8397 |
"coprocessor must be in the range [p0, p7]"); |
| 8398 |
break; |
8398 |
break; |
| 8399 |
} |
8399 |
} |
| 8400 |
|
8400 |
|
| 8401 |
case ARM::t2CDP: |
8401 |
case ARM::t2CDP: |
| 8402 |
case ARM::t2CDP2: |
8402 |
case ARM::t2CDP2: |
| 8403 |
case ARM::t2LDC2L_OFFSET: |
8403 |
case ARM::t2LDC2L_OFFSET: |
| 8404 |
case ARM::t2LDC2L_OPTION: |
8404 |
case ARM::t2LDC2L_OPTION: |
| 8405 |
case ARM::t2LDC2L_POST: |
8405 |
case ARM::t2LDC2L_POST: |
| 8406 |
case ARM::t2LDC2L_PRE: |
8406 |
case ARM::t2LDC2L_PRE: |
| 8407 |
case ARM::t2LDC2_OFFSET: |
8407 |
case ARM::t2LDC2_OFFSET: |
| 8408 |
case ARM::t2LDC2_OPTION: |
8408 |
case ARM::t2LDC2_OPTION: |
| 8409 |
case ARM::t2LDC2_POST: |
8409 |
case ARM::t2LDC2_POST: |
| 8410 |
case ARM::t2LDC2_PRE: |
8410 |
case ARM::t2LDC2_PRE: |
| 8411 |
case ARM::t2LDCL_OFFSET: |
8411 |
case ARM::t2LDCL_OFFSET: |
| 8412 |
case ARM::t2LDCL_OPTION: |
8412 |
case ARM::t2LDCL_OPTION: |
| 8413 |
case ARM::t2LDCL_POST: |
8413 |
case ARM::t2LDCL_POST: |
| 8414 |
case ARM::t2LDCL_PRE: |
8414 |
case ARM::t2LDCL_PRE: |
| 8415 |
case ARM::t2LDC_OFFSET: |
8415 |
case ARM::t2LDC_OFFSET: |
| 8416 |
case ARM::t2LDC_OPTION: |
8416 |
case ARM::t2LDC_OPTION: |
| 8417 |
case ARM::t2LDC_POST: |
8417 |
case ARM::t2LDC_POST: |
| 8418 |
case ARM::t2LDC_PRE: |
8418 |
case ARM::t2LDC_PRE: |
| 8419 |
case ARM::t2MCR: |
8419 |
case ARM::t2MCR: |
| 8420 |
case ARM::t2MCR2: |
8420 |
case ARM::t2MCR2: |
| 8421 |
case ARM::t2MCRR: |
8421 |
case ARM::t2MCRR: |
| 8422 |
case ARM::t2MCRR2: |
8422 |
case ARM::t2MCRR2: |
| 8423 |
case ARM::t2MRC: |
8423 |
case ARM::t2MRC: |
| 8424 |
case ARM::t2MRC2: |
8424 |
case ARM::t2MRC2: |
| 8425 |
case ARM::t2MRRC: |
8425 |
case ARM::t2MRRC: |
| 8426 |
case ARM::t2MRRC2: |
8426 |
case ARM::t2MRRC2: |
| 8427 |
case ARM::t2STC2L_OFFSET: |
8427 |
case ARM::t2STC2L_OFFSET: |
| 8428 |
case ARM::t2STC2L_OPTION: |
8428 |
case ARM::t2STC2L_OPTION: |
| 8429 |
case ARM::t2STC2L_POST: |
8429 |
case ARM::t2STC2L_POST: |
| 8430 |
case ARM::t2STC2L_PRE: |
8430 |
case ARM::t2STC2L_PRE: |
| 8431 |
case ARM::t2STC2_OFFSET: |
8431 |
case ARM::t2STC2_OFFSET: |
| 8432 |
case ARM::t2STC2_OPTION: |
8432 |
case ARM::t2STC2_OPTION: |
| 8433 |
case ARM::t2STC2_POST: |
8433 |
case ARM::t2STC2_POST: |
| 8434 |
case ARM::t2STC2_PRE: |
8434 |
case ARM::t2STC2_PRE: |
| 8435 |
case ARM::t2STCL_OFFSET: |
8435 |
case ARM::t2STCL_OFFSET: |
| 8436 |
case ARM::t2STCL_OPTION: |
8436 |
case ARM::t2STCL_OPTION: |
| 8437 |
case ARM::t2STCL_POST: |
8437 |
case ARM::t2STCL_POST: |
| 8438 |
case ARM::t2STCL_PRE: |
8438 |
case ARM::t2STCL_PRE: |
| 8439 |
case ARM::t2STC_OFFSET: |
8439 |
case ARM::t2STC_OFFSET: |
| 8440 |
case ARM::t2STC_OPTION: |
8440 |
case ARM::t2STC_OPTION: |
| 8441 |
case ARM::t2STC_POST: |
8441 |
case ARM::t2STC_POST: |
| 8442 |
case ARM::t2STC_PRE: { |
8442 |
case ARM::t2STC_PRE: { |
| 8443 |
unsigned Opcode = Inst.getOpcode(); |
8443 |
unsigned Opcode = Inst.getOpcode(); |
| 8444 |
// Inst.getOperand indexes operands in the (oops ...) and (iops ...) dags, |
8444 |
// Inst.getOperand indexes operands in the (oops ...) and (iops ...) dags, |
| 8445 |
// CopInd is the index of the coprocessor operand. |
8445 |
// CopInd is the index of the coprocessor operand. |
| 8446 |
size_t CopInd = 0; |
8446 |
size_t CopInd = 0; |
| 8447 |
if (Opcode == ARM::t2MRRC || Opcode == ARM::t2MRRC2) |
8447 |
if (Opcode == ARM::t2MRRC || Opcode == ARM::t2MRRC2) |
| 8448 |
CopInd = 2; |
8448 |
CopInd = 2; |
| 8449 |
else if (Opcode == ARM::t2MRC || Opcode == ARM::t2MRC2) |
8449 |
else if (Opcode == ARM::t2MRC || Opcode == ARM::t2MRC2) |
| 8450 |
CopInd = 1; |
8450 |
CopInd = 1; |
| 8451 |
assert(Inst.getOperand(CopInd).isImm() && |
8451 |
assert(Inst.getOperand(CopInd).isImm() && |
| 8452 |
"Operand must be a coprocessor ID"); |
8452 |
"Operand must be a coprocessor ID"); |
| 8453 |
int64_t Coproc = Inst.getOperand(CopInd).getImm(); |
8453 |
int64_t Coproc = Inst.getOperand(CopInd).getImm(); |
| 8454 |
// Operands[2] is the coprocessor operand at syntactic level |
8454 |
// Operands[2] is the coprocessor operand at syntactic level |
| 8455 |
if (ARM::isCDECoproc(Coproc, *STI)) |
8455 |
if (ARM::isCDECoproc(Coproc, *STI)) |
| 8456 |
return Error(Operands[2]->getStartLoc(), |
8456 |
return Error(Operands[2]->getStartLoc(), |
| 8457 |
"coprocessor must be configured as GCP"); |
8457 |
"coprocessor must be configured as GCP"); |
| 8458 |
break; |
8458 |
break; |
| 8459 |
} |
8459 |
} |
| 8460 |
} |
8460 |
} |
| 8461 |
|
8461 |
|
| 8462 |
return false; |
8462 |
return false; |
| 8463 |
} |
8463 |
} |
| 8464 |
|
8464 |
|
| 8465 |
static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) { |
8465 |
static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) { |
| 8466 |
switch(Opc) { |
8466 |
switch(Opc) { |
| 8467 |
default: llvm_unreachable("unexpected opcode!"); |
8467 |
default: llvm_unreachable("unexpected opcode!"); |
| 8468 |
// VST1LN |
8468 |
// VST1LN |
| 8469 |
case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD; |
8469 |
case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD; |
| 8470 |
case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD; |
8470 |
case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD; |
| 8471 |
case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD; |
8471 |
case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD; |
| 8472 |
case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD; |
8472 |
case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD; |
| 8473 |
case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD; |
8473 |
case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD; |
| 8474 |
case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD; |
8474 |
case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD; |
| 8475 |
case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8; |
8475 |
case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8; |
| 8476 |
case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16; |
8476 |
case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16; |
| 8477 |
case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32; |
8477 |
case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32; |
| 8478 |
|
8478 |
|
| 8479 |
// VST2LN |
8479 |
// VST2LN |
| 8480 |
case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD; |
8480 |
case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD; |
| 8481 |
case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD; |
8481 |
case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD; |
| 8482 |
case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD; |
8482 |
case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD; |
| 8483 |
case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD; |
8483 |
case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD; |
| 8484 |
case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD; |
8484 |
case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD; |
| 8485 |
|
8485 |
|
| 8486 |
case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD; |
8486 |
case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD; |
| 8487 |
case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD; |
8487 |
case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD; |
| 8488 |
case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD; |
8488 |
case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD; |
| 8489 |
case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD; |
8489 |
case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD; |
| 8490 |
case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD; |
8490 |
case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD; |
| 8491 |
|
8491 |
|
| 8492 |
case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8; |
8492 |
case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8; |
| 8493 |
case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16; |
8493 |
case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16; |
| 8494 |
case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32; |
8494 |
case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32; |
| 8495 |
case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16; |
8495 |
case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16; |
| 8496 |
case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32; |
8496 |
case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32; |
| 8497 |
|
8497 |
|
| 8498 |
// VST3LN |
8498 |
// VST3LN |
| 8499 |
case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD; |
8499 |
case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD; |
| 8500 |
case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD; |
8500 |
case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD; |
| 8501 |
case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD; |
8501 |
case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD; |
| 8502 |
case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD; |
8502 |
case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD; |
| 8503 |
case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD; |
8503 |
case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD; |
| 8504 |
case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD; |
8504 |
case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD; |
| 8505 |
case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD; |
8505 |
case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD; |
| 8506 |
case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD; |
8506 |
case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD; |
| 8507 |
case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD; |
8507 |
case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD; |
| 8508 |
case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD; |
8508 |
case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD; |
| 8509 |
case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8; |
8509 |
case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8; |
| 8510 |
case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16; |
8510 |
case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16; |
| 8511 |
case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32; |
8511 |
case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32; |
| 8512 |
case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16; |
8512 |
case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16; |
| 8513 |
case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32; |
8513 |
case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32; |
| 8514 |
|
8514 |
|
| 8515 |
// VST3 |
8515 |
// VST3 |
| 8516 |
case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD; |
8516 |
case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD; |
| 8517 |
case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD; |
8517 |
case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD; |
| 8518 |
case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD; |
8518 |
case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD; |
| 8519 |
case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD; |
8519 |
case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD; |
| 8520 |
case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD; |
8520 |
case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD; |
| 8521 |
case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD; |
8521 |
case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD; |
| 8522 |
case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD; |
8522 |
case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD; |
| 8523 |
case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD; |
8523 |
case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD; |
| 8524 |
case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD; |
8524 |
case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD; |
| 8525 |
case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD; |
8525 |
case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD; |
| 8526 |
case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD; |
8526 |
case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD; |
| 8527 |
case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD; |
8527 |
case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD; |
| 8528 |
case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8; |
8528 |
case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8; |
| 8529 |
case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16; |
8529 |
case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16; |
| 8530 |
case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32; |
8530 |
case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32; |
| 8531 |
case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8; |
8531 |
case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8; |
| 8532 |
case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16; |
8532 |
case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16; |
| 8533 |
case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32; |
8533 |
case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32; |
| 8534 |
|
8534 |
|
| 8535 |
// VST4LN |
8535 |
// VST4LN |
| 8536 |
case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD; |
8536 |
case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD; |
| 8537 |
case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD; |
8537 |
case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD; |
| 8538 |
case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD; |
8538 |
case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD; |
| 8539 |
case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD; |
8539 |
case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD; |
| 8540 |
case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD; |
8540 |
case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD; |
| 8541 |
case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD; |
8541 |
case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD; |
| 8542 |
case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD; |
8542 |
case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD; |
| 8543 |
case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD; |
8543 |
case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD; |
| 8544 |
case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD; |
8544 |
case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD; |
| 8545 |
case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD; |
8545 |
case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD; |
| 8546 |
case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8; |
8546 |
case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8; |
| 8547 |
case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16; |
8547 |
case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16; |
| 8548 |
case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32; |
8548 |
case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32; |
| 8549 |
case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16; |
8549 |
case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16; |
| 8550 |
case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32; |
8550 |
case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32; |
| 8551 |
|
8551 |
|
| 8552 |
// VST4 |
8552 |
// VST4 |
| 8553 |
case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD; |
8553 |
case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD; |
| 8554 |
case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD; |
8554 |
case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD; |
| 8555 |
case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD; |
8555 |
case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD; |
| 8556 |
case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD; |
8556 |
case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD; |
| 8557 |
case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD; |
8557 |
case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD; |
| 8558 |
case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD; |
8558 |
case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD; |
| 8559 |
case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD; |
8559 |
case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD; |
| 8560 |
case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD; |
8560 |
case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD; |
| 8561 |
case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD; |
8561 |
case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD; |
| 8562 |
case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD; |
8562 |
case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD; |
| 8563 |
case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD; |
8563 |
case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD; |
| 8564 |
case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD; |
8564 |
case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD; |
| 8565 |
case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8; |
8565 |
case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8; |
| 8566 |
case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16; |
8566 |
case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16; |
| 8567 |
case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32; |
8567 |
case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32; |
| 8568 |
case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8; |
8568 |
case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8; |
| 8569 |
case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16; |
8569 |
case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16; |
| 8570 |
case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32; |
8570 |
case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32; |
| 8571 |
} |
8571 |
} |
| 8572 |
} |
8572 |
} |
| 8573 |
|
8573 |
|
| 8574 |
static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) { |
8574 |
static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) { |
| 8575 |
switch(Opc) { |
8575 |
switch(Opc) { |
| 8576 |
default: llvm_unreachable("unexpected opcode!"); |
8576 |
default: llvm_unreachable("unexpected opcode!"); |
| 8577 |
// VLD1LN |
8577 |
// VLD1LN |
| 8578 |
case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD; |
8578 |
case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD; |
| 8579 |
case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD; |
8579 |
case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD; |
| 8580 |
case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD; |
8580 |
case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD; |
| 8581 |
case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD; |
8581 |
case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD; |
| 8582 |
case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD; |
8582 |
case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD; |
| 8583 |
case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD; |
8583 |
case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD; |
| 8584 |
case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8; |
8584 |
case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8; |
| 8585 |
case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16; |
8585 |
case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16; |
| 8586 |
case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32; |
8586 |
case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32; |
| 8587 |
|
8587 |
|
| 8588 |
// VLD2LN |
8588 |
// VLD2LN |
| 8589 |
case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD; |
8589 |
case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD; |
| 8590 |
case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD; |
8590 |
case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD; |
| 8591 |
case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD; |
8591 |
case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD; |
| 8592 |
case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD; |
8592 |
case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD; |
| 8593 |
case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD; |
8593 |
case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD; |
| 8594 |
case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD; |
8594 |
case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD; |
| 8595 |
case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD; |
8595 |
case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD; |
| 8596 |
case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD; |
8596 |
case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD; |
| 8597 |
case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD; |
8597 |
case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD; |
| 8598 |
case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD; |
8598 |
case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD; |
| 8599 |
case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8; |
8599 |
case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8; |
| 8600 |
case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16; |
8600 |
case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16; |
| 8601 |
case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32; |
8601 |
case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32; |
| 8602 |
case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16; |
8602 |
case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16; |
| 8603 |
case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32; |
8603 |
case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32; |
| 8604 |
|
8604 |
|
| 8605 |
// VLD3DUP |
8605 |
// VLD3DUP |
| 8606 |
case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD; |
8606 |
case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD; |
| 8607 |
case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD; |
8607 |
case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD; |
| 8608 |
case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD; |
8608 |
case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD; |
| 8609 |
case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD; |
8609 |
case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD; |
| 8610 |
case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD; |
8610 |
case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD; |
| 8611 |
case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD; |
8611 |
case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD; |
| 8612 |
case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD; |
8612 |
case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD; |
| 8613 |
case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD; |
8613 |
case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD; |
| 8614 |
case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD; |
8614 |
case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD; |
| 8615 |
case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD; |
8615 |
case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD; |
| 8616 |
case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD; |
8616 |
case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD; |
| 8617 |
case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD; |
8617 |
case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD; |
| 8618 |
case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8; |
8618 |
case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8; |
| 8619 |
case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16; |
8619 |
case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16; |
| 8620 |
case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32; |
8620 |
case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32; |
| 8621 |
case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8; |
8621 |
case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8; |
| 8622 |
case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16; |
8622 |
case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16; |
| 8623 |
case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32; |
8623 |
case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32; |
| 8624 |
|
8624 |
|
| 8625 |
// VLD3LN |
8625 |
// VLD3LN |
| 8626 |
case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD; |
8626 |
case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD; |
| 8627 |
case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD; |
8627 |
case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD; |
| 8628 |
case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD; |
8628 |
case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD; |
| 8629 |
case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD; |
8629 |
case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD; |
| 8630 |
case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD; |
8630 |
case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD; |
| 8631 |
case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD; |
8631 |
case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD; |
| 8632 |
case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD; |
8632 |
case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD; |
| 8633 |
case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD; |
8633 |
case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD; |
| 8634 |
case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD; |
8634 |
case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD; |
| 8635 |
case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD; |
8635 |
case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD; |
| 8636 |
case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8; |
8636 |
case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8; |
| 8637 |
case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16; |
8637 |
case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16; |
| 8638 |
case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32; |
8638 |
case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32; |
| 8639 |
case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16; |
8639 |
case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16; |
| 8640 |
case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32; |
8640 |
case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32; |
| 8641 |
|
8641 |
|
| 8642 |
// VLD3 |
8642 |
// VLD3 |
| 8643 |
case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD; |
8643 |
case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD; |
| 8644 |
case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD; |
8644 |
case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD; |
| 8645 |
case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD; |
8645 |
case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD; |
| 8646 |
case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD; |
8646 |
case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD; |
| 8647 |
case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD; |
8647 |
case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD; |
| 8648 |
case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD; |
8648 |
case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD; |
| 8649 |
case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD; |
8649 |
case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD; |
| 8650 |
case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD; |
8650 |
case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD; |
| 8651 |
case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD; |
8651 |
case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD; |
| 8652 |
case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD; |
8652 |
case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD; |
| 8653 |
case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD; |
8653 |
case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD; |
| 8654 |
case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD; |
8654 |
case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD; |
| 8655 |
case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8; |
8655 |
case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8; |
| 8656 |
case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16; |
8656 |
case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16; |
| 8657 |
case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32; |
8657 |
case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32; |
| 8658 |
case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8; |
8658 |
case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8; |
| 8659 |
case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16; |
8659 |
case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16; |
| 8660 |
case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32; |
8660 |
case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32; |
| 8661 |
|
8661 |
|
| 8662 |
// VLD4LN |
8662 |
// VLD4LN |
| 8663 |
case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD; |
8663 |
case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD; |
| 8664 |
case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD; |
8664 |
case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD; |
| 8665 |
case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD; |
8665 |
case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD; |
| 8666 |
case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD; |
8666 |
case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD; |
| 8667 |
case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD; |
8667 |
case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD; |
| 8668 |
case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD; |
8668 |
case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD; |
| 8669 |
case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD; |
8669 |
case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD; |
| 8670 |
case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD; |
8670 |
case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD; |
| 8671 |
case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD; |
8671 |
case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD; |
| 8672 |
case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD; |
8672 |
case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD; |
| 8673 |
case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8; |
8673 |
case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8; |
| 8674 |
case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16; |
8674 |
case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16; |
| 8675 |
case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32; |
8675 |
case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32; |
| 8676 |
case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16; |
8676 |
case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16; |
| 8677 |
case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32; |
8677 |
case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32; |
| 8678 |
|
8678 |
|
| 8679 |
// VLD4DUP |
8679 |
// VLD4DUP |
| 8680 |
case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD; |
8680 |
case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD; |
| 8681 |
case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD; |
8681 |
case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD; |
| 8682 |
case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD; |
8682 |
case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD; |
| 8683 |
case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD; |
8683 |
case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD; |
| 8684 |
case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD; |
8684 |
case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD; |
| 8685 |
case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD; |
8685 |
case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD; |
| 8686 |
case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD; |
8686 |
case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD; |
| 8687 |
case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD; |
8687 |
case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD; |
| 8688 |
case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD; |
8688 |
case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD; |
| 8689 |
case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD; |
8689 |
case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD; |
| 8690 |
case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD; |
8690 |
case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD; |
| 8691 |
case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD; |
8691 |
case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD; |
| 8692 |
case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8; |
8692 |
case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8; |
| 8693 |
case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16; |
8693 |
case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16; |
| 8694 |
case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32; |
8694 |
case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32; |
| 8695 |
case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8; |
8695 |
case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8; |
| 8696 |
case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16; |
8696 |
case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16; |
| 8697 |
case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32; |
8697 |
case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32; |
| 8698 |
|
8698 |
|
| 8699 |
// VLD4 |
8699 |
// VLD4 |
| 8700 |
case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD; |
8700 |
case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD; |
| 8701 |
case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD; |
8701 |
case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD; |
| 8702 |
case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD; |
8702 |
case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD; |
| 8703 |
case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD; |
8703 |
case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD; |
| 8704 |
case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD; |
8704 |
case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD; |
| 8705 |
case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD; |
8705 |
case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD; |
| 8706 |
case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD; |
8706 |
case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD; |
| 8707 |
case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD; |
8707 |
case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD; |
| 8708 |
case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD; |
8708 |
case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD; |
| 8709 |
case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD; |
8709 |
case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD; |
| 8710 |
case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD; |
8710 |
case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD; |
| 8711 |
case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD; |
8711 |
case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD; |
| 8712 |
case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8; |
8712 |
case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8; |
| 8713 |
case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16; |
8713 |
case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16; |
| 8714 |
case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32; |
8714 |
case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32; |
| 8715 |
case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8; |
8715 |
case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8; |
| 8716 |
case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16; |
8716 |
case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16; |
| 8717 |
case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32; |
8717 |
case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32; |
| 8718 |
} |
8718 |
} |
| 8719 |
} |
8719 |
} |
| 8720 |
|
8720 |
|
| 8721 |
bool ARMAsmParser::processInstruction(MCInst &Inst, |
8721 |
bool ARMAsmParser::processInstruction(MCInst &Inst, |
| 8722 |
const OperandVector &Operands, |
8722 |
const OperandVector &Operands, |
| 8723 |
MCStreamer &Out) { |
8723 |
MCStreamer &Out) { |
| 8724 |
// Check if we have the wide qualifier, because if it's present we |
8724 |
// Check if we have the wide qualifier, because if it's present we |
| 8725 |
// must avoid selecting a 16-bit thumb instruction. |
8725 |
// must avoid selecting a 16-bit thumb instruction. |
| 8726 |
bool HasWideQualifier = false; |
8726 |
bool HasWideQualifier = false; |
| 8727 |
for (auto &Op : Operands) { |
8727 |
for (auto &Op : Operands) { |
| 8728 |
ARMOperand &ARMOp = static_cast(*Op); |
8728 |
ARMOperand &ARMOp = static_cast(*Op); |
| 8729 |
if (ARMOp.isToken() && ARMOp.getToken() == ".w") { |
8729 |
if (ARMOp.isToken() && ARMOp.getToken() == ".w") { |
| 8730 |
HasWideQualifier = true; |
8730 |
HasWideQualifier = true; |
| 8731 |
break; |
8731 |
break; |
| 8732 |
} |
8732 |
} |
| 8733 |
} |
8733 |
} |
| 8734 |
|
8734 |
|
| 8735 |
switch (Inst.getOpcode()) { |
8735 |
switch (Inst.getOpcode()) { |
| 8736 |
// Alias for alternate form of 'ldr{,b}t Rt, [Rn], #imm' instruction. |
8736 |
// Alias for alternate form of 'ldr{,b}t Rt, [Rn], #imm' instruction. |
| 8737 |
case ARM::LDRT_POST: |
8737 |
case ARM::LDRT_POST: |
| 8738 |
case ARM::LDRBT_POST: { |
8738 |
case ARM::LDRBT_POST: { |
| 8739 |
const unsigned Opcode = |
8739 |
const unsigned Opcode = |
| 8740 |
(Inst.getOpcode() == ARM::LDRT_POST) ? ARM::LDRT_POST_IMM |
8740 |
(Inst.getOpcode() == ARM::LDRT_POST) ? ARM::LDRT_POST_IMM |
| 8741 |
: ARM::LDRBT_POST_IMM; |
8741 |
: ARM::LDRBT_POST_IMM; |
| 8742 |
MCInst TmpInst; |
8742 |
MCInst TmpInst; |
| 8743 |
TmpInst.setOpcode(Opcode); |
8743 |
TmpInst.setOpcode(Opcode); |
| 8744 |
TmpInst.addOperand(Inst.getOperand(0)); |
8744 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 8745 |
TmpInst.addOperand(Inst.getOperand(1)); |
8745 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 8746 |
TmpInst.addOperand(Inst.getOperand(1)); |
8746 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 8747 |
TmpInst.addOperand(MCOperand::createReg(0)); |
8747 |
TmpInst.addOperand(MCOperand::createReg(0)); |
| 8748 |
TmpInst.addOperand(MCOperand::createImm(0)); |
8748 |
TmpInst.addOperand(MCOperand::createImm(0)); |
| 8749 |
TmpInst.addOperand(Inst.getOperand(2)); |
8749 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 8750 |
TmpInst.addOperand(Inst.getOperand(3)); |
8750 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 8751 |
Inst = TmpInst; |
8751 |
Inst = TmpInst; |
| 8752 |
return true; |
8752 |
return true; |
| 8753 |
} |
8753 |
} |
| 8754 |
// Alias for 'ldr{sb,h,sh}t Rt, [Rn] {, #imm}' for ommitted immediate. |
8754 |
// Alias for 'ldr{sb,h,sh}t Rt, [Rn] {, #imm}' for ommitted immediate. |
| 8755 |
case ARM::LDRSBTii: |
8755 |
case ARM::LDRSBTii: |
| 8756 |
case ARM::LDRHTii: |
8756 |
case ARM::LDRHTii: |
| 8757 |
case ARM::LDRSHTii: { |
8757 |
case ARM::LDRSHTii: { |
| 8758 |
MCInst TmpInst; |
8758 |
MCInst TmpInst; |
| 8759 |
|
8759 |
|
| 8760 |
if (Inst.getOpcode() == ARM::LDRSBTii) |
8760 |
if (Inst.getOpcode() == ARM::LDRSBTii) |
| 8761 |
TmpInst.setOpcode(ARM::LDRSBTi); |
8761 |
TmpInst.setOpcode(ARM::LDRSBTi); |
| 8762 |
else if (Inst.getOpcode() == ARM::LDRHTii) |
8762 |
else if (Inst.getOpcode() == ARM::LDRHTii) |
| 8763 |
TmpInst.setOpcode(ARM::LDRHTi); |
8763 |
TmpInst.setOpcode(ARM::LDRHTi); |
| 8764 |
else if (Inst.getOpcode() == ARM::LDRSHTii) |
8764 |
else if (Inst.getOpcode() == ARM::LDRSHTii) |
| 8765 |
TmpInst.setOpcode(ARM::LDRSHTi); |
8765 |
TmpInst.setOpcode(ARM::LDRSHTi); |
| 8766 |
TmpInst.addOperand(Inst.getOperand(0)); |
8766 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 8767 |
TmpInst.addOperand(Inst.getOperand(1)); |
8767 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 8768 |
TmpInst.addOperand(Inst.getOperand(1)); |
8768 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 8769 |
TmpInst.addOperand(MCOperand::createImm(256)); |
8769 |
TmpInst.addOperand(MCOperand::createImm(256)); |
| 8770 |
TmpInst.addOperand(Inst.getOperand(2)); |
8770 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 8771 |
Inst = TmpInst; |
8771 |
Inst = TmpInst; |
| 8772 |
return true; |
8772 |
return true; |
| 8773 |
} |
8773 |
} |
| 8774 |
// Alias for alternate form of 'str{,b}t Rt, [Rn], #imm' instruction. |
8774 |
// Alias for alternate form of 'str{,b}t Rt, [Rn], #imm' instruction. |
| 8775 |
case ARM::STRT_POST: |
8775 |
case ARM::STRT_POST: |
| 8776 |
case ARM::STRBT_POST: { |
8776 |
case ARM::STRBT_POST: { |
| 8777 |
const unsigned Opcode = |
8777 |
const unsigned Opcode = |
| 8778 |
(Inst.getOpcode() == ARM::STRT_POST) ? ARM::STRT_POST_IMM |
8778 |
(Inst.getOpcode() == ARM::STRT_POST) ? ARM::STRT_POST_IMM |
| 8779 |
: ARM::STRBT_POST_IMM; |
8779 |
: ARM::STRBT_POST_IMM; |
| 8780 |
MCInst TmpInst; |
8780 |
MCInst TmpInst; |
| 8781 |
TmpInst.setOpcode(Opcode); |
8781 |
TmpInst.setOpcode(Opcode); |
| 8782 |
TmpInst.addOperand(Inst.getOperand(1)); |
8782 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 8783 |
TmpInst.addOperand(Inst.getOperand(0)); |
8783 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 8784 |
TmpInst.addOperand(Inst.getOperand(1)); |
8784 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 8785 |
TmpInst.addOperand(MCOperand::createReg(0)); |
8785 |
TmpInst.addOperand(MCOperand::createReg(0)); |
| 8786 |
TmpInst.addOperand(MCOperand::createImm(0)); |
8786 |
TmpInst.addOperand(MCOperand::createImm(0)); |
| 8787 |
TmpInst.addOperand(Inst.getOperand(2)); |
8787 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 8788 |
TmpInst.addOperand(Inst.getOperand(3)); |
8788 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 8789 |
Inst = TmpInst; |
8789 |
Inst = TmpInst; |
| 8790 |
return true; |
8790 |
return true; |
| 8791 |
} |
8791 |
} |
| 8792 |
// Alias for alternate form of 'ADR Rd, #imm' instruction. |
8792 |
// Alias for alternate form of 'ADR Rd, #imm' instruction. |
| 8793 |
case ARM::ADDri: { |
8793 |
case ARM::ADDri: { |
| 8794 |
if (Inst.getOperand(1).getReg() != ARM::PC || |
8794 |
if (Inst.getOperand(1).getReg() != ARM::PC || |
| 8795 |
Inst.getOperand(5).getReg() != 0 || |
8795 |
Inst.getOperand(5).getReg() != 0 || |
| 8796 |
!(Inst.getOperand(2).isExpr() || Inst.getOperand(2).isImm())) |
8796 |
!(Inst.getOperand(2).isExpr() || Inst.getOperand(2).isImm())) |
| 8797 |
return false; |
8797 |
return false; |
| 8798 |
MCInst TmpInst; |
8798 |
MCInst TmpInst; |
| 8799 |
TmpInst.setOpcode(ARM::ADR); |
8799 |
TmpInst.setOpcode(ARM::ADR); |
| 8800 |
TmpInst.addOperand(Inst.getOperand(0)); |
8800 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 8801 |
if (Inst.getOperand(2).isImm()) { |
8801 |
if (Inst.getOperand(2).isImm()) { |
| 8802 |
// Immediate (mod_imm) will be in its encoded form, we must unencode it |
8802 |
// Immediate (mod_imm) will be in its encoded form, we must unencode it |
| 8803 |
// before passing it to the ADR instruction. |
8803 |
// before passing it to the ADR instruction. |
| 8804 |
unsigned Enc = Inst.getOperand(2).getImm(); |
8804 |
unsigned Enc = Inst.getOperand(2).getImm(); |
| 8805 |
TmpInst.addOperand(MCOperand::createImm( |
8805 |
TmpInst.addOperand(MCOperand::createImm( |
| 8806 |
llvm::rotr(Enc & 0xFF, (Enc & 0xF00) >> 7))); |
8806 |
llvm::rotr(Enc & 0xFF, (Enc & 0xF00) >> 7))); |
| 8807 |
} else { |
8807 |
} else { |
| 8808 |
// Turn PC-relative expression into absolute expression. |
8808 |
// Turn PC-relative expression into absolute expression. |
| 8809 |
// Reading PC provides the start of the current instruction + 8 and |
8809 |
// Reading PC provides the start of the current instruction + 8 and |
| 8810 |
// the transform to adr is biased by that. |
8810 |
// the transform to adr is biased by that. |
| 8811 |
MCSymbol *Dot = getContext().createTempSymbol(); |
8811 |
MCSymbol *Dot = getContext().createTempSymbol(); |
| 8812 |
Out.emitLabel(Dot); |
8812 |
Out.emitLabel(Dot); |
| 8813 |
const MCExpr *OpExpr = Inst.getOperand(2).getExpr(); |
8813 |
const MCExpr *OpExpr = Inst.getOperand(2).getExpr(); |
| 8814 |
const MCExpr *InstPC = MCSymbolRefExpr::create(Dot, |
8814 |
const MCExpr *InstPC = MCSymbolRefExpr::create(Dot, |
| 8815 |
MCSymbolRefExpr::VK_None, |
8815 |
MCSymbolRefExpr::VK_None, |
| 8816 |
getContext()); |
8816 |
getContext()); |
| 8817 |
const MCExpr *Const8 = MCConstantExpr::create(8, getContext()); |
8817 |
const MCExpr *Const8 = MCConstantExpr::create(8, getContext()); |
| 8818 |
const MCExpr *ReadPC = MCBinaryExpr::createAdd(InstPC, Const8, |
8818 |
const MCExpr *ReadPC = MCBinaryExpr::createAdd(InstPC, Const8, |
| 8819 |
getContext()); |
8819 |
getContext()); |
| 8820 |
const MCExpr *FixupAddr = MCBinaryExpr::createAdd(ReadPC, OpExpr, |
8820 |
const MCExpr *FixupAddr = MCBinaryExpr::createAdd(ReadPC, OpExpr, |
| 8821 |
getContext()); |
8821 |
getContext()); |
| 8822 |
TmpInst.addOperand(MCOperand::createExpr(FixupAddr)); |
8822 |
TmpInst.addOperand(MCOperand::createExpr(FixupAddr)); |
| 8823 |
} |
8823 |
} |
| 8824 |
TmpInst.addOperand(Inst.getOperand(3)); |
8824 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 8825 |
TmpInst.addOperand(Inst.getOperand(4)); |
8825 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 8826 |
Inst = TmpInst; |
8826 |
Inst = TmpInst; |
| 8827 |
return true; |
8827 |
return true; |
| 8828 |
} |
8828 |
} |
| 8829 |
// Aliases for imm syntax of LDR instructions. |
8829 |
// Aliases for imm syntax of LDR instructions. |
| 8830 |
case ARM::t2LDR_PRE_imm: |
8830 |
case ARM::t2LDR_PRE_imm: |
| 8831 |
case ARM::t2LDR_POST_imm: { |
8831 |
case ARM::t2LDR_POST_imm: { |
| 8832 |
MCInst TmpInst; |
8832 |
MCInst TmpInst; |
| 8833 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDR_PRE_imm ? ARM::t2LDR_PRE |
8833 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDR_PRE_imm ? ARM::t2LDR_PRE |
| 8834 |
: ARM::t2LDR_POST); |
8834 |
: ARM::t2LDR_POST); |
| 8835 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8835 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8836 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
8836 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
| 8837 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8837 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8838 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8838 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8839 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8839 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8840 |
Inst = TmpInst; |
8840 |
Inst = TmpInst; |
| 8841 |
return true; |
8841 |
return true; |
| 8842 |
} |
8842 |
} |
| 8843 |
// Aliases for imm syntax of STR instructions. |
8843 |
// Aliases for imm syntax of STR instructions. |
| 8844 |
case ARM::t2STR_PRE_imm: |
8844 |
case ARM::t2STR_PRE_imm: |
| 8845 |
case ARM::t2STR_POST_imm: { |
8845 |
case ARM::t2STR_POST_imm: { |
| 8846 |
MCInst TmpInst; |
8846 |
MCInst TmpInst; |
| 8847 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2STR_PRE_imm ? ARM::t2STR_PRE |
8847 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2STR_PRE_imm ? ARM::t2STR_PRE |
| 8848 |
: ARM::t2STR_POST); |
8848 |
: ARM::t2STR_POST); |
| 8849 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
8849 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
| 8850 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8850 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8851 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8851 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8852 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8852 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8853 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8853 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8854 |
Inst = TmpInst; |
8854 |
Inst = TmpInst; |
| 8855 |
return true; |
8855 |
return true; |
| 8856 |
} |
8856 |
} |
| 8857 |
// Aliases for imm syntax of LDRB instructions. |
8857 |
// Aliases for imm syntax of LDRB instructions. |
| 8858 |
case ARM::t2LDRB_OFFSET_imm: { |
8858 |
case ARM::t2LDRB_OFFSET_imm: { |
| 8859 |
MCInst TmpInst; |
8859 |
MCInst TmpInst; |
| 8860 |
TmpInst.setOpcode(ARM::t2LDRBi8); |
8860 |
TmpInst.setOpcode(ARM::t2LDRBi8); |
| 8861 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8861 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8862 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8862 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8863 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8863 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8864 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8864 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8865 |
Inst = TmpInst; |
8865 |
Inst = TmpInst; |
| 8866 |
return true; |
8866 |
return true; |
| 8867 |
} |
8867 |
} |
| 8868 |
case ARM::t2LDRB_PRE_imm: |
8868 |
case ARM::t2LDRB_PRE_imm: |
| 8869 |
case ARM::t2LDRB_POST_imm: { |
8869 |
case ARM::t2LDRB_POST_imm: { |
| 8870 |
MCInst TmpInst; |
8870 |
MCInst TmpInst; |
| 8871 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDRB_PRE_imm |
8871 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDRB_PRE_imm |
| 8872 |
? ARM::t2LDRB_PRE |
8872 |
? ARM::t2LDRB_PRE |
| 8873 |
: ARM::t2LDRB_POST); |
8873 |
: ARM::t2LDRB_POST); |
| 8874 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8874 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8875 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
8875 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
| 8876 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8876 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8877 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8877 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8878 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8878 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8879 |
Inst = TmpInst; |
8879 |
Inst = TmpInst; |
| 8880 |
return true; |
8880 |
return true; |
| 8881 |
} |
8881 |
} |
| 8882 |
// Aliases for imm syntax of STRB instructions. |
8882 |
// Aliases for imm syntax of STRB instructions. |
| 8883 |
case ARM::t2STRB_OFFSET_imm: { |
8883 |
case ARM::t2STRB_OFFSET_imm: { |
| 8884 |
MCInst TmpInst; |
8884 |
MCInst TmpInst; |
| 8885 |
TmpInst.setOpcode(ARM::t2STRBi8); |
8885 |
TmpInst.setOpcode(ARM::t2STRBi8); |
| 8886 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8886 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8887 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8887 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8888 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8888 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8889 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8889 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8890 |
Inst = TmpInst; |
8890 |
Inst = TmpInst; |
| 8891 |
return true; |
8891 |
return true; |
| 8892 |
} |
8892 |
} |
| 8893 |
case ARM::t2STRB_PRE_imm: |
8893 |
case ARM::t2STRB_PRE_imm: |
| 8894 |
case ARM::t2STRB_POST_imm: { |
8894 |
case ARM::t2STRB_POST_imm: { |
| 8895 |
MCInst TmpInst; |
8895 |
MCInst TmpInst; |
| 8896 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2STRB_PRE_imm |
8896 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2STRB_PRE_imm |
| 8897 |
? ARM::t2STRB_PRE |
8897 |
? ARM::t2STRB_PRE |
| 8898 |
: ARM::t2STRB_POST); |
8898 |
: ARM::t2STRB_POST); |
| 8899 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
8899 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
| 8900 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8900 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8901 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8901 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8902 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8902 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8903 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8903 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8904 |
Inst = TmpInst; |
8904 |
Inst = TmpInst; |
| 8905 |
return true; |
8905 |
return true; |
| 8906 |
} |
8906 |
} |
| 8907 |
// Aliases for imm syntax of LDRH instructions. |
8907 |
// Aliases for imm syntax of LDRH instructions. |
| 8908 |
case ARM::t2LDRH_OFFSET_imm: { |
8908 |
case ARM::t2LDRH_OFFSET_imm: { |
| 8909 |
MCInst TmpInst; |
8909 |
MCInst TmpInst; |
| 8910 |
TmpInst.setOpcode(ARM::t2LDRHi8); |
8910 |
TmpInst.setOpcode(ARM::t2LDRHi8); |
| 8911 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8911 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8912 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8912 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8913 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8913 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8914 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8914 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8915 |
Inst = TmpInst; |
8915 |
Inst = TmpInst; |
| 8916 |
return true; |
8916 |
return true; |
| 8917 |
} |
8917 |
} |
| 8918 |
case ARM::t2LDRH_PRE_imm: |
8918 |
case ARM::t2LDRH_PRE_imm: |
| 8919 |
case ARM::t2LDRH_POST_imm: { |
8919 |
case ARM::t2LDRH_POST_imm: { |
| 8920 |
MCInst TmpInst; |
8920 |
MCInst TmpInst; |
| 8921 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDRH_PRE_imm |
8921 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDRH_PRE_imm |
| 8922 |
? ARM::t2LDRH_PRE |
8922 |
? ARM::t2LDRH_PRE |
| 8923 |
: ARM::t2LDRH_POST); |
8923 |
: ARM::t2LDRH_POST); |
| 8924 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8924 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8925 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
8925 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
| 8926 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8926 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8927 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8927 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8928 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8928 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8929 |
Inst = TmpInst; |
8929 |
Inst = TmpInst; |
| 8930 |
return true; |
8930 |
return true; |
| 8931 |
} |
8931 |
} |
| 8932 |
// Aliases for imm syntax of STRH instructions. |
8932 |
// Aliases for imm syntax of STRH instructions. |
| 8933 |
case ARM::t2STRH_OFFSET_imm: { |
8933 |
case ARM::t2STRH_OFFSET_imm: { |
| 8934 |
MCInst TmpInst; |
8934 |
MCInst TmpInst; |
| 8935 |
TmpInst.setOpcode(ARM::t2STRHi8); |
8935 |
TmpInst.setOpcode(ARM::t2STRHi8); |
| 8936 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8936 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8937 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8937 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8938 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8938 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8939 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8939 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8940 |
Inst = TmpInst; |
8940 |
Inst = TmpInst; |
| 8941 |
return true; |
8941 |
return true; |
| 8942 |
} |
8942 |
} |
| 8943 |
case ARM::t2STRH_PRE_imm: |
8943 |
case ARM::t2STRH_PRE_imm: |
| 8944 |
case ARM::t2STRH_POST_imm: { |
8944 |
case ARM::t2STRH_POST_imm: { |
| 8945 |
MCInst TmpInst; |
8945 |
MCInst TmpInst; |
| 8946 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2STRH_PRE_imm |
8946 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2STRH_PRE_imm |
| 8947 |
? ARM::t2STRH_PRE |
8947 |
? ARM::t2STRH_PRE |
| 8948 |
: ARM::t2STRH_POST); |
8948 |
: ARM::t2STRH_POST); |
| 8949 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
8949 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
| 8950 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8950 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8951 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8951 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8952 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8952 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8953 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8953 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8954 |
Inst = TmpInst; |
8954 |
Inst = TmpInst; |
| 8955 |
return true; |
8955 |
return true; |
| 8956 |
} |
8956 |
} |
| 8957 |
// Aliases for imm syntax of LDRSB instructions. |
8957 |
// Aliases for imm syntax of LDRSB instructions. |
| 8958 |
case ARM::t2LDRSB_OFFSET_imm: { |
8958 |
case ARM::t2LDRSB_OFFSET_imm: { |
| 8959 |
MCInst TmpInst; |
8959 |
MCInst TmpInst; |
| 8960 |
TmpInst.setOpcode(ARM::t2LDRSBi8); |
8960 |
TmpInst.setOpcode(ARM::t2LDRSBi8); |
| 8961 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8961 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8962 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8962 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8963 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8963 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8964 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8964 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8965 |
Inst = TmpInst; |
8965 |
Inst = TmpInst; |
| 8966 |
return true; |
8966 |
return true; |
| 8967 |
} |
8967 |
} |
| 8968 |
case ARM::t2LDRSB_PRE_imm: |
8968 |
case ARM::t2LDRSB_PRE_imm: |
| 8969 |
case ARM::t2LDRSB_POST_imm: { |
8969 |
case ARM::t2LDRSB_POST_imm: { |
| 8970 |
MCInst TmpInst; |
8970 |
MCInst TmpInst; |
| 8971 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDRSB_PRE_imm |
8971 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDRSB_PRE_imm |
| 8972 |
? ARM::t2LDRSB_PRE |
8972 |
? ARM::t2LDRSB_PRE |
| 8973 |
: ARM::t2LDRSB_POST); |
8973 |
: ARM::t2LDRSB_POST); |
| 8974 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8974 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8975 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
8975 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
| 8976 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8976 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8977 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8977 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8978 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8978 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8979 |
Inst = TmpInst; |
8979 |
Inst = TmpInst; |
| 8980 |
return true; |
8980 |
return true; |
| 8981 |
} |
8981 |
} |
| 8982 |
// Aliases for imm syntax of LDRSH instructions. |
8982 |
// Aliases for imm syntax of LDRSH instructions. |
| 8983 |
case ARM::t2LDRSH_OFFSET_imm: { |
8983 |
case ARM::t2LDRSH_OFFSET_imm: { |
| 8984 |
MCInst TmpInst; |
8984 |
MCInst TmpInst; |
| 8985 |
TmpInst.setOpcode(ARM::t2LDRSHi8); |
8985 |
TmpInst.setOpcode(ARM::t2LDRSHi8); |
| 8986 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8986 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 8987 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
8987 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 8988 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
8988 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 8989 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
8989 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 8990 |
Inst = TmpInst; |
8990 |
Inst = TmpInst; |
| 8991 |
return true; |
8991 |
return true; |
| 8992 |
} |
8992 |
} |
| 8993 |
case ARM::t2LDRSH_PRE_imm: |
8993 |
case ARM::t2LDRSH_PRE_imm: |
| 8994 |
case ARM::t2LDRSH_POST_imm: { |
8994 |
case ARM::t2LDRSH_POST_imm: { |
| 8995 |
MCInst TmpInst; |
8995 |
MCInst TmpInst; |
| 8996 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDRSH_PRE_imm |
8996 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDRSH_PRE_imm |
| 8997 |
? ARM::t2LDRSH_PRE |
8997 |
? ARM::t2LDRSH_PRE |
| 8998 |
: ARM::t2LDRSH_POST); |
8998 |
: ARM::t2LDRSH_POST); |
| 8999 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
8999 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 9000 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
9000 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb |
| 9001 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9001 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9002 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
9002 |
TmpInst.addOperand(Inst.getOperand(2)); // imm |
| 9003 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
9003 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 9004 |
Inst = TmpInst; |
9004 |
Inst = TmpInst; |
| 9005 |
return true; |
9005 |
return true; |
| 9006 |
} |
9006 |
} |
| 9007 |
// Aliases for alternate PC+imm syntax of LDR instructions. |
9007 |
// Aliases for alternate PC+imm syntax of LDR instructions. |
| 9008 |
case ARM::t2LDRpcrel: |
9008 |
case ARM::t2LDRpcrel: |
| 9009 |
// Select the narrow version if the immediate will fit. |
9009 |
// Select the narrow version if the immediate will fit. |
| 9010 |
if (Inst.getOperand(1).getImm() > 0 && |
9010 |
if (Inst.getOperand(1).getImm() > 0 && |
| 9011 |
Inst.getOperand(1).getImm() <= 0xff && |
9011 |
Inst.getOperand(1).getImm() <= 0xff && |
| 9012 |
!HasWideQualifier) |
9012 |
!HasWideQualifier) |
| 9013 |
Inst.setOpcode(ARM::tLDRpci); |
9013 |
Inst.setOpcode(ARM::tLDRpci); |
| 9014 |
else |
9014 |
else |
| 9015 |
Inst.setOpcode(ARM::t2LDRpci); |
9015 |
Inst.setOpcode(ARM::t2LDRpci); |
| 9016 |
return true; |
9016 |
return true; |
| 9017 |
case ARM::t2LDRBpcrel: |
9017 |
case ARM::t2LDRBpcrel: |
| 9018 |
Inst.setOpcode(ARM::t2LDRBpci); |
9018 |
Inst.setOpcode(ARM::t2LDRBpci); |
| 9019 |
return true; |
9019 |
return true; |
| 9020 |
case ARM::t2LDRHpcrel: |
9020 |
case ARM::t2LDRHpcrel: |
| 9021 |
Inst.setOpcode(ARM::t2LDRHpci); |
9021 |
Inst.setOpcode(ARM::t2LDRHpci); |
| 9022 |
return true; |
9022 |
return true; |
| 9023 |
case ARM::t2LDRSBpcrel: |
9023 |
case ARM::t2LDRSBpcrel: |
| 9024 |
Inst.setOpcode(ARM::t2LDRSBpci); |
9024 |
Inst.setOpcode(ARM::t2LDRSBpci); |
| 9025 |
return true; |
9025 |
return true; |
| 9026 |
case ARM::t2LDRSHpcrel: |
9026 |
case ARM::t2LDRSHpcrel: |
| 9027 |
Inst.setOpcode(ARM::t2LDRSHpci); |
9027 |
Inst.setOpcode(ARM::t2LDRSHpci); |
| 9028 |
return true; |
9028 |
return true; |
| 9029 |
case ARM::LDRConstPool: |
9029 |
case ARM::LDRConstPool: |
| 9030 |
case ARM::tLDRConstPool: |
9030 |
case ARM::tLDRConstPool: |
| 9031 |
case ARM::t2LDRConstPool: { |
9031 |
case ARM::t2LDRConstPool: { |
| 9032 |
// Pseudo instruction ldr rt, =immediate is converted to a |
9032 |
// Pseudo instruction ldr rt, =immediate is converted to a |
| 9033 |
// MOV rt, immediate if immediate is known and representable |
9033 |
// MOV rt, immediate if immediate is known and representable |
| 9034 |
// otherwise we create a constant pool entry that we load from. |
9034 |
// otherwise we create a constant pool entry that we load from. |
| 9035 |
MCInst TmpInst; |
9035 |
MCInst TmpInst; |
| 9036 |
if (Inst.getOpcode() == ARM::LDRConstPool) |
9036 |
if (Inst.getOpcode() == ARM::LDRConstPool) |
| 9037 |
TmpInst.setOpcode(ARM::LDRi12); |
9037 |
TmpInst.setOpcode(ARM::LDRi12); |
| 9038 |
else if (Inst.getOpcode() == ARM::tLDRConstPool) |
9038 |
else if (Inst.getOpcode() == ARM::tLDRConstPool) |
| 9039 |
TmpInst.setOpcode(ARM::tLDRpci); |
9039 |
TmpInst.setOpcode(ARM::tLDRpci); |
| 9040 |
else if (Inst.getOpcode() == ARM::t2LDRConstPool) |
9040 |
else if (Inst.getOpcode() == ARM::t2LDRConstPool) |
| 9041 |
TmpInst.setOpcode(ARM::t2LDRpci); |
9041 |
TmpInst.setOpcode(ARM::t2LDRpci); |
| 9042 |
const ARMOperand &PoolOperand = |
9042 |
const ARMOperand &PoolOperand = |
| 9043 |
(HasWideQualifier ? |
9043 |
(HasWideQualifier ? |
| 9044 |
static_cast(*Operands[4]) : |
9044 |
static_cast(*Operands[4]) : |
| 9045 |
static_cast(*Operands[3])); |
9045 |
static_cast(*Operands[3])); |
| 9046 |
const MCExpr *SubExprVal = PoolOperand.getConstantPoolImm(); |
9046 |
const MCExpr *SubExprVal = PoolOperand.getConstantPoolImm(); |
| 9047 |
// If SubExprVal is a constant we may be able to use a MOV |
9047 |
// If SubExprVal is a constant we may be able to use a MOV |
| 9048 |
if (isa(SubExprVal) && |
9048 |
if (isa(SubExprVal) && |
| 9049 |
Inst.getOperand(0).getReg() != ARM::PC && |
9049 |
Inst.getOperand(0).getReg() != ARM::PC && |
| 9050 |
Inst.getOperand(0).getReg() != ARM::SP) { |
9050 |
Inst.getOperand(0).getReg() != ARM::SP) { |
| 9051 |
int64_t Value = |
9051 |
int64_t Value = |
| 9052 |
(int64_t) (cast(SubExprVal))->getValue(); |
9052 |
(int64_t) (cast(SubExprVal))->getValue(); |
| 9053 |
bool UseMov = true; |
9053 |
bool UseMov = true; |
| 9054 |
bool MovHasS = true; |
9054 |
bool MovHasS = true; |
| 9055 |
if (Inst.getOpcode() == ARM::LDRConstPool) { |
9055 |
if (Inst.getOpcode() == ARM::LDRConstPool) { |
| 9056 |
// ARM Constant |
9056 |
// ARM Constant |
| 9057 |
if (ARM_AM::getSOImmVal(Value) != -1) { |
9057 |
if (ARM_AM::getSOImmVal(Value) != -1) { |
| 9058 |
Value = ARM_AM::getSOImmVal(Value); |
9058 |
Value = ARM_AM::getSOImmVal(Value); |
| 9059 |
TmpInst.setOpcode(ARM::MOVi); |
9059 |
TmpInst.setOpcode(ARM::MOVi); |
| 9060 |
} |
9060 |
} |
| 9061 |
else if (ARM_AM::getSOImmVal(~Value) != -1) { |
9061 |
else if (ARM_AM::getSOImmVal(~Value) != -1) { |
| 9062 |
Value = ARM_AM::getSOImmVal(~Value); |
9062 |
Value = ARM_AM::getSOImmVal(~Value); |
| 9063 |
TmpInst.setOpcode(ARM::MVNi); |
9063 |
TmpInst.setOpcode(ARM::MVNi); |
| 9064 |
} |
9064 |
} |
| 9065 |
else if (hasV6T2Ops() && |
9065 |
else if (hasV6T2Ops() && |
| 9066 |
Value >=0 && Value < 65536) { |
9066 |
Value >=0 && Value < 65536) { |
| 9067 |
TmpInst.setOpcode(ARM::MOVi16); |
9067 |
TmpInst.setOpcode(ARM::MOVi16); |
| 9068 |
MovHasS = false; |
9068 |
MovHasS = false; |
| 9069 |
} |
9069 |
} |
| 9070 |
else |
9070 |
else |
| 9071 |
UseMov = false; |
9071 |
UseMov = false; |
| 9072 |
} |
9072 |
} |
| 9073 |
else { |
9073 |
else { |
| 9074 |
// Thumb/Thumb2 Constant |
9074 |
// Thumb/Thumb2 Constant |
| 9075 |
if (hasThumb2() && |
9075 |
if (hasThumb2() && |
| 9076 |
ARM_AM::getT2SOImmVal(Value) != -1) |
9076 |
ARM_AM::getT2SOImmVal(Value) != -1) |
| 9077 |
TmpInst.setOpcode(ARM::t2MOVi); |
9077 |
TmpInst.setOpcode(ARM::t2MOVi); |
| 9078 |
else if (hasThumb2() && |
9078 |
else if (hasThumb2() && |
| 9079 |
ARM_AM::getT2SOImmVal(~Value) != -1) { |
9079 |
ARM_AM::getT2SOImmVal(~Value) != -1) { |
| 9080 |
TmpInst.setOpcode(ARM::t2MVNi); |
9080 |
TmpInst.setOpcode(ARM::t2MVNi); |
| 9081 |
Value = ~Value; |
9081 |
Value = ~Value; |
| 9082 |
} |
9082 |
} |
| 9083 |
else if (hasV8MBaseline() && |
9083 |
else if (hasV8MBaseline() && |
| 9084 |
Value >=0 && Value < 65536) { |
9084 |
Value >=0 && Value < 65536) { |
| 9085 |
TmpInst.setOpcode(ARM::t2MOVi16); |
9085 |
TmpInst.setOpcode(ARM::t2MOVi16); |
| 9086 |
MovHasS = false; |
9086 |
MovHasS = false; |
| 9087 |
} |
9087 |
} |
| 9088 |
else |
9088 |
else |
| 9089 |
UseMov = false; |
9089 |
UseMov = false; |
| 9090 |
} |
9090 |
} |
| 9091 |
if (UseMov) { |
9091 |
if (UseMov) { |
| 9092 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
9092 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 9093 |
TmpInst.addOperand(MCOperand::createImm(Value)); // Immediate |
9093 |
TmpInst.addOperand(MCOperand::createImm(Value)); // Immediate |
| 9094 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
9094 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
| 9095 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
9095 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 9096 |
if (MovHasS) |
9096 |
if (MovHasS) |
| 9097 |
TmpInst.addOperand(MCOperand::createReg(0)); // S |
9097 |
TmpInst.addOperand(MCOperand::createReg(0)); // S |
| 9098 |
Inst = TmpInst; |
9098 |
Inst = TmpInst; |
| 9099 |
return true; |
9099 |
return true; |
| 9100 |
} |
9100 |
} |
| 9101 |
} |
9101 |
} |
| 9102 |
// No opportunity to use MOV/MVN create constant pool |
9102 |
// No opportunity to use MOV/MVN create constant pool |
| 9103 |
const MCExpr *CPLoc = |
9103 |
const MCExpr *CPLoc = |
| 9104 |
getTargetStreamer().addConstantPoolEntry(SubExprVal, |
9104 |
getTargetStreamer().addConstantPoolEntry(SubExprVal, |
| 9105 |
PoolOperand.getStartLoc()); |
9105 |
PoolOperand.getStartLoc()); |
| 9106 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
9106 |
TmpInst.addOperand(Inst.getOperand(0)); // Rt |
| 9107 |
TmpInst.addOperand(MCOperand::createExpr(CPLoc)); // offset to constpool |
9107 |
TmpInst.addOperand(MCOperand::createExpr(CPLoc)); // offset to constpool |
| 9108 |
if (TmpInst.getOpcode() == ARM::LDRi12) |
9108 |
if (TmpInst.getOpcode() == ARM::LDRi12) |
| 9109 |
TmpInst.addOperand(MCOperand::createImm(0)); // unused offset |
9109 |
TmpInst.addOperand(MCOperand::createImm(0)); // unused offset |
| 9110 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
9110 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
| 9111 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
9111 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 9112 |
Inst = TmpInst; |
9112 |
Inst = TmpInst; |
| 9113 |
return true; |
9113 |
return true; |
| 9114 |
} |
9114 |
} |
| 9115 |
// Handle NEON VST complex aliases. |
9115 |
// Handle NEON VST complex aliases. |
| 9116 |
case ARM::VST1LNdWB_register_Asm_8: |
9116 |
case ARM::VST1LNdWB_register_Asm_8: |
| 9117 |
case ARM::VST1LNdWB_register_Asm_16: |
9117 |
case ARM::VST1LNdWB_register_Asm_16: |
| 9118 |
case ARM::VST1LNdWB_register_Asm_32: { |
9118 |
case ARM::VST1LNdWB_register_Asm_32: { |
| 9119 |
MCInst TmpInst; |
9119 |
MCInst TmpInst; |
| 9120 |
// Shuffle the operands around so the lane index operand is in the |
9120 |
// Shuffle the operands around so the lane index operand is in the |
| 9121 |
// right place. |
9121 |
// right place. |
| 9122 |
unsigned Spacing; |
9122 |
unsigned Spacing; |
| 9123 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9123 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9124 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9124 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9125 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9125 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9126 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9126 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9127 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
9127 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
| 9128 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9128 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9129 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9129 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9130 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
9130 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
| 9131 |
TmpInst.addOperand(Inst.getOperand(6)); |
9131 |
TmpInst.addOperand(Inst.getOperand(6)); |
| 9132 |
Inst = TmpInst; |
9132 |
Inst = TmpInst; |
| 9133 |
return true; |
9133 |
return true; |
| 9134 |
} |
9134 |
} |
| 9135 |
|
9135 |
|
| 9136 |
case ARM::VST2LNdWB_register_Asm_8: |
9136 |
case ARM::VST2LNdWB_register_Asm_8: |
| 9137 |
case ARM::VST2LNdWB_register_Asm_16: |
9137 |
case ARM::VST2LNdWB_register_Asm_16: |
| 9138 |
case ARM::VST2LNdWB_register_Asm_32: |
9138 |
case ARM::VST2LNdWB_register_Asm_32: |
| 9139 |
case ARM::VST2LNqWB_register_Asm_16: |
9139 |
case ARM::VST2LNqWB_register_Asm_16: |
| 9140 |
case ARM::VST2LNqWB_register_Asm_32: { |
9140 |
case ARM::VST2LNqWB_register_Asm_32: { |
| 9141 |
MCInst TmpInst; |
9141 |
MCInst TmpInst; |
| 9142 |
// Shuffle the operands around so the lane index operand is in the |
9142 |
// Shuffle the operands around so the lane index operand is in the |
| 9143 |
// right place. |
9143 |
// right place. |
| 9144 |
unsigned Spacing; |
9144 |
unsigned Spacing; |
| 9145 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9145 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9146 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9146 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9147 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9147 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9148 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9148 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9149 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
9149 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
| 9150 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9150 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9151 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9151 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9152 |
Spacing)); |
9152 |
Spacing)); |
| 9153 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9153 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9154 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
9154 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
| 9155 |
TmpInst.addOperand(Inst.getOperand(6)); |
9155 |
TmpInst.addOperand(Inst.getOperand(6)); |
| 9156 |
Inst = TmpInst; |
9156 |
Inst = TmpInst; |
| 9157 |
return true; |
9157 |
return true; |
| 9158 |
} |
9158 |
} |
| 9159 |
|
9159 |
|
| 9160 |
case ARM::VST3LNdWB_register_Asm_8: |
9160 |
case ARM::VST3LNdWB_register_Asm_8: |
| 9161 |
case ARM::VST3LNdWB_register_Asm_16: |
9161 |
case ARM::VST3LNdWB_register_Asm_16: |
| 9162 |
case ARM::VST3LNdWB_register_Asm_32: |
9162 |
case ARM::VST3LNdWB_register_Asm_32: |
| 9163 |
case ARM::VST3LNqWB_register_Asm_16: |
9163 |
case ARM::VST3LNqWB_register_Asm_16: |
| 9164 |
case ARM::VST3LNqWB_register_Asm_32: { |
9164 |
case ARM::VST3LNqWB_register_Asm_32: { |
| 9165 |
MCInst TmpInst; |
9165 |
MCInst TmpInst; |
| 9166 |
// Shuffle the operands around so the lane index operand is in the |
9166 |
// Shuffle the operands around so the lane index operand is in the |
| 9167 |
// right place. |
9167 |
// right place. |
| 9168 |
unsigned Spacing; |
9168 |
unsigned Spacing; |
| 9169 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9169 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9170 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9170 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9171 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9171 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9172 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9172 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9173 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
9173 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
| 9174 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9174 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9175 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9175 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9176 |
Spacing)); |
9176 |
Spacing)); |
| 9177 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9177 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9178 |
Spacing * 2)); |
9178 |
Spacing * 2)); |
| 9179 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9179 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9180 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
9180 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
| 9181 |
TmpInst.addOperand(Inst.getOperand(6)); |
9181 |
TmpInst.addOperand(Inst.getOperand(6)); |
| 9182 |
Inst = TmpInst; |
9182 |
Inst = TmpInst; |
| 9183 |
return true; |
9183 |
return true; |
| 9184 |
} |
9184 |
} |
| 9185 |
|
9185 |
|
| 9186 |
case ARM::VST4LNdWB_register_Asm_8: |
9186 |
case ARM::VST4LNdWB_register_Asm_8: |
| 9187 |
case ARM::VST4LNdWB_register_Asm_16: |
9187 |
case ARM::VST4LNdWB_register_Asm_16: |
| 9188 |
case ARM::VST4LNdWB_register_Asm_32: |
9188 |
case ARM::VST4LNdWB_register_Asm_32: |
| 9189 |
case ARM::VST4LNqWB_register_Asm_16: |
9189 |
case ARM::VST4LNqWB_register_Asm_16: |
| 9190 |
case ARM::VST4LNqWB_register_Asm_32: { |
9190 |
case ARM::VST4LNqWB_register_Asm_32: { |
| 9191 |
MCInst TmpInst; |
9191 |
MCInst TmpInst; |
| 9192 |
// Shuffle the operands around so the lane index operand is in the |
9192 |
// Shuffle the operands around so the lane index operand is in the |
| 9193 |
// right place. |
9193 |
// right place. |
| 9194 |
unsigned Spacing; |
9194 |
unsigned Spacing; |
| 9195 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9195 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9196 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9196 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9197 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9197 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9198 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9198 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9199 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
9199 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
| 9200 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9200 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9201 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9201 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9202 |
Spacing)); |
9202 |
Spacing)); |
| 9203 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9203 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9204 |
Spacing * 2)); |
9204 |
Spacing * 2)); |
| 9205 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9205 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9206 |
Spacing * 3)); |
9206 |
Spacing * 3)); |
| 9207 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9207 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9208 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
9208 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
| 9209 |
TmpInst.addOperand(Inst.getOperand(6)); |
9209 |
TmpInst.addOperand(Inst.getOperand(6)); |
| 9210 |
Inst = TmpInst; |
9210 |
Inst = TmpInst; |
| 9211 |
return true; |
9211 |
return true; |
| 9212 |
} |
9212 |
} |
| 9213 |
|
9213 |
|
| 9214 |
case ARM::VST1LNdWB_fixed_Asm_8: |
9214 |
case ARM::VST1LNdWB_fixed_Asm_8: |
| 9215 |
case ARM::VST1LNdWB_fixed_Asm_16: |
9215 |
case ARM::VST1LNdWB_fixed_Asm_16: |
| 9216 |
case ARM::VST1LNdWB_fixed_Asm_32: { |
9216 |
case ARM::VST1LNdWB_fixed_Asm_32: { |
| 9217 |
MCInst TmpInst; |
9217 |
MCInst TmpInst; |
| 9218 |
// Shuffle the operands around so the lane index operand is in the |
9218 |
// Shuffle the operands around so the lane index operand is in the |
| 9219 |
// right place. |
9219 |
// right place. |
| 9220 |
unsigned Spacing; |
9220 |
unsigned Spacing; |
| 9221 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9221 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9222 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9222 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9223 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9223 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9224 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9224 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9225 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9225 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9226 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9226 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9227 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9227 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9228 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9228 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9229 |
TmpInst.addOperand(Inst.getOperand(5)); |
9229 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9230 |
Inst = TmpInst; |
9230 |
Inst = TmpInst; |
| 9231 |
return true; |
9231 |
return true; |
| 9232 |
} |
9232 |
} |
| 9233 |
|
9233 |
|
| 9234 |
case ARM::VST2LNdWB_fixed_Asm_8: |
9234 |
case ARM::VST2LNdWB_fixed_Asm_8: |
| 9235 |
case ARM::VST2LNdWB_fixed_Asm_16: |
9235 |
case ARM::VST2LNdWB_fixed_Asm_16: |
| 9236 |
case ARM::VST2LNdWB_fixed_Asm_32: |
9236 |
case ARM::VST2LNdWB_fixed_Asm_32: |
| 9237 |
case ARM::VST2LNqWB_fixed_Asm_16: |
9237 |
case ARM::VST2LNqWB_fixed_Asm_16: |
| 9238 |
case ARM::VST2LNqWB_fixed_Asm_32: { |
9238 |
case ARM::VST2LNqWB_fixed_Asm_32: { |
| 9239 |
MCInst TmpInst; |
9239 |
MCInst TmpInst; |
| 9240 |
// Shuffle the operands around so the lane index operand is in the |
9240 |
// Shuffle the operands around so the lane index operand is in the |
| 9241 |
// right place. |
9241 |
// right place. |
| 9242 |
unsigned Spacing; |
9242 |
unsigned Spacing; |
| 9243 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9243 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9244 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9244 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9245 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9245 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9246 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9246 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9247 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9247 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9248 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9248 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9249 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9249 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9250 |
Spacing)); |
9250 |
Spacing)); |
| 9251 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9251 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9252 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9252 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9253 |
TmpInst.addOperand(Inst.getOperand(5)); |
9253 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9254 |
Inst = TmpInst; |
9254 |
Inst = TmpInst; |
| 9255 |
return true; |
9255 |
return true; |
| 9256 |
} |
9256 |
} |
| 9257 |
|
9257 |
|
| 9258 |
case ARM::VST3LNdWB_fixed_Asm_8: |
9258 |
case ARM::VST3LNdWB_fixed_Asm_8: |
| 9259 |
case ARM::VST3LNdWB_fixed_Asm_16: |
9259 |
case ARM::VST3LNdWB_fixed_Asm_16: |
| 9260 |
case ARM::VST3LNdWB_fixed_Asm_32: |
9260 |
case ARM::VST3LNdWB_fixed_Asm_32: |
| 9261 |
case ARM::VST3LNqWB_fixed_Asm_16: |
9261 |
case ARM::VST3LNqWB_fixed_Asm_16: |
| 9262 |
case ARM::VST3LNqWB_fixed_Asm_32: { |
9262 |
case ARM::VST3LNqWB_fixed_Asm_32: { |
| 9263 |
MCInst TmpInst; |
9263 |
MCInst TmpInst; |
| 9264 |
// Shuffle the operands around so the lane index operand is in the |
9264 |
// Shuffle the operands around so the lane index operand is in the |
| 9265 |
// right place. |
9265 |
// right place. |
| 9266 |
unsigned Spacing; |
9266 |
unsigned Spacing; |
| 9267 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9267 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9268 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9268 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9269 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9269 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9270 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9270 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9271 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9271 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9272 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9272 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9273 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9273 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9274 |
Spacing)); |
9274 |
Spacing)); |
| 9275 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9275 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9276 |
Spacing * 2)); |
9276 |
Spacing * 2)); |
| 9277 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9277 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9278 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9278 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9279 |
TmpInst.addOperand(Inst.getOperand(5)); |
9279 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9280 |
Inst = TmpInst; |
9280 |
Inst = TmpInst; |
| 9281 |
return true; |
9281 |
return true; |
| 9282 |
} |
9282 |
} |
| 9283 |
|
9283 |
|
| 9284 |
case ARM::VST4LNdWB_fixed_Asm_8: |
9284 |
case ARM::VST4LNdWB_fixed_Asm_8: |
| 9285 |
case ARM::VST4LNdWB_fixed_Asm_16: |
9285 |
case ARM::VST4LNdWB_fixed_Asm_16: |
| 9286 |
case ARM::VST4LNdWB_fixed_Asm_32: |
9286 |
case ARM::VST4LNdWB_fixed_Asm_32: |
| 9287 |
case ARM::VST4LNqWB_fixed_Asm_16: |
9287 |
case ARM::VST4LNqWB_fixed_Asm_16: |
| 9288 |
case ARM::VST4LNqWB_fixed_Asm_32: { |
9288 |
case ARM::VST4LNqWB_fixed_Asm_32: { |
| 9289 |
MCInst TmpInst; |
9289 |
MCInst TmpInst; |
| 9290 |
// Shuffle the operands around so the lane index operand is in the |
9290 |
// Shuffle the operands around so the lane index operand is in the |
| 9291 |
// right place. |
9291 |
// right place. |
| 9292 |
unsigned Spacing; |
9292 |
unsigned Spacing; |
| 9293 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9293 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9294 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9294 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9295 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9295 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9296 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9296 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9297 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9297 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9298 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9298 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9299 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9299 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9300 |
Spacing)); |
9300 |
Spacing)); |
| 9301 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9301 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9302 |
Spacing * 2)); |
9302 |
Spacing * 2)); |
| 9303 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9303 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9304 |
Spacing * 3)); |
9304 |
Spacing * 3)); |
| 9305 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9305 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9306 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9306 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9307 |
TmpInst.addOperand(Inst.getOperand(5)); |
9307 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9308 |
Inst = TmpInst; |
9308 |
Inst = TmpInst; |
| 9309 |
return true; |
9309 |
return true; |
| 9310 |
} |
9310 |
} |
| 9311 |
|
9311 |
|
| 9312 |
case ARM::VST1LNdAsm_8: |
9312 |
case ARM::VST1LNdAsm_8: |
| 9313 |
case ARM::VST1LNdAsm_16: |
9313 |
case ARM::VST1LNdAsm_16: |
| 9314 |
case ARM::VST1LNdAsm_32: { |
9314 |
case ARM::VST1LNdAsm_32: { |
| 9315 |
MCInst TmpInst; |
9315 |
MCInst TmpInst; |
| 9316 |
// Shuffle the operands around so the lane index operand is in the |
9316 |
// Shuffle the operands around so the lane index operand is in the |
| 9317 |
// right place. |
9317 |
// right place. |
| 9318 |
unsigned Spacing; |
9318 |
unsigned Spacing; |
| 9319 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9319 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9320 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9320 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9321 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9321 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9322 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9322 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9323 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9323 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9324 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9324 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9325 |
TmpInst.addOperand(Inst.getOperand(5)); |
9325 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9326 |
Inst = TmpInst; |
9326 |
Inst = TmpInst; |
| 9327 |
return true; |
9327 |
return true; |
| 9328 |
} |
9328 |
} |
| 9329 |
|
9329 |
|
| 9330 |
case ARM::VST2LNdAsm_8: |
9330 |
case ARM::VST2LNdAsm_8: |
| 9331 |
case ARM::VST2LNdAsm_16: |
9331 |
case ARM::VST2LNdAsm_16: |
| 9332 |
case ARM::VST2LNdAsm_32: |
9332 |
case ARM::VST2LNdAsm_32: |
| 9333 |
case ARM::VST2LNqAsm_16: |
9333 |
case ARM::VST2LNqAsm_16: |
| 9334 |
case ARM::VST2LNqAsm_32: { |
9334 |
case ARM::VST2LNqAsm_32: { |
| 9335 |
MCInst TmpInst; |
9335 |
MCInst TmpInst; |
| 9336 |
// Shuffle the operands around so the lane index operand is in the |
9336 |
// Shuffle the operands around so the lane index operand is in the |
| 9337 |
// right place. |
9337 |
// right place. |
| 9338 |
unsigned Spacing; |
9338 |
unsigned Spacing; |
| 9339 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9339 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9340 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9340 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9341 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9341 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9342 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9342 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9343 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9343 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9344 |
Spacing)); |
9344 |
Spacing)); |
| 9345 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9345 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9346 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9346 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9347 |
TmpInst.addOperand(Inst.getOperand(5)); |
9347 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9348 |
Inst = TmpInst; |
9348 |
Inst = TmpInst; |
| 9349 |
return true; |
9349 |
return true; |
| 9350 |
} |
9350 |
} |
| 9351 |
|
9351 |
|
| 9352 |
case ARM::VST3LNdAsm_8: |
9352 |
case ARM::VST3LNdAsm_8: |
| 9353 |
case ARM::VST3LNdAsm_16: |
9353 |
case ARM::VST3LNdAsm_16: |
| 9354 |
case ARM::VST3LNdAsm_32: |
9354 |
case ARM::VST3LNdAsm_32: |
| 9355 |
case ARM::VST3LNqAsm_16: |
9355 |
case ARM::VST3LNqAsm_16: |
| 9356 |
case ARM::VST3LNqAsm_32: { |
9356 |
case ARM::VST3LNqAsm_32: { |
| 9357 |
MCInst TmpInst; |
9357 |
MCInst TmpInst; |
| 9358 |
// Shuffle the operands around so the lane index operand is in the |
9358 |
// Shuffle the operands around so the lane index operand is in the |
| 9359 |
// right place. |
9359 |
// right place. |
| 9360 |
unsigned Spacing; |
9360 |
unsigned Spacing; |
| 9361 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9361 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9362 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9362 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9363 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9363 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9364 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9364 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9365 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9365 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9366 |
Spacing)); |
9366 |
Spacing)); |
| 9367 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9367 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9368 |
Spacing * 2)); |
9368 |
Spacing * 2)); |
| 9369 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9369 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9370 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9370 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9371 |
TmpInst.addOperand(Inst.getOperand(5)); |
9371 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9372 |
Inst = TmpInst; |
9372 |
Inst = TmpInst; |
| 9373 |
return true; |
9373 |
return true; |
| 9374 |
} |
9374 |
} |
| 9375 |
|
9375 |
|
| 9376 |
case ARM::VST4LNdAsm_8: |
9376 |
case ARM::VST4LNdAsm_8: |
| 9377 |
case ARM::VST4LNdAsm_16: |
9377 |
case ARM::VST4LNdAsm_16: |
| 9378 |
case ARM::VST4LNdAsm_32: |
9378 |
case ARM::VST4LNdAsm_32: |
| 9379 |
case ARM::VST4LNqAsm_16: |
9379 |
case ARM::VST4LNqAsm_16: |
| 9380 |
case ARM::VST4LNqAsm_32: { |
9380 |
case ARM::VST4LNqAsm_32: { |
| 9381 |
MCInst TmpInst; |
9381 |
MCInst TmpInst; |
| 9382 |
// Shuffle the operands around so the lane index operand is in the |
9382 |
// Shuffle the operands around so the lane index operand is in the |
| 9383 |
// right place. |
9383 |
// right place. |
| 9384 |
unsigned Spacing; |
9384 |
unsigned Spacing; |
| 9385 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
9385 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 9386 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9386 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9387 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9387 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9388 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9388 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9389 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9389 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9390 |
Spacing)); |
9390 |
Spacing)); |
| 9391 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9391 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9392 |
Spacing * 2)); |
9392 |
Spacing * 2)); |
| 9393 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9393 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9394 |
Spacing * 3)); |
9394 |
Spacing * 3)); |
| 9395 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9395 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9396 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9396 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9397 |
TmpInst.addOperand(Inst.getOperand(5)); |
9397 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9398 |
Inst = TmpInst; |
9398 |
Inst = TmpInst; |
| 9399 |
return true; |
9399 |
return true; |
| 9400 |
} |
9400 |
} |
| 9401 |
|
9401 |
|
| 9402 |
// Handle NEON VLD complex aliases. |
9402 |
// Handle NEON VLD complex aliases. |
| 9403 |
case ARM::VLD1LNdWB_register_Asm_8: |
9403 |
case ARM::VLD1LNdWB_register_Asm_8: |
| 9404 |
case ARM::VLD1LNdWB_register_Asm_16: |
9404 |
case ARM::VLD1LNdWB_register_Asm_16: |
| 9405 |
case ARM::VLD1LNdWB_register_Asm_32: { |
9405 |
case ARM::VLD1LNdWB_register_Asm_32: { |
| 9406 |
MCInst TmpInst; |
9406 |
MCInst TmpInst; |
| 9407 |
// Shuffle the operands around so the lane index operand is in the |
9407 |
// Shuffle the operands around so the lane index operand is in the |
| 9408 |
// right place. |
9408 |
// right place. |
| 9409 |
unsigned Spacing; |
9409 |
unsigned Spacing; |
| 9410 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9410 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9411 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9411 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9412 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9412 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9413 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9413 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9414 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9414 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9415 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
9415 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
| 9416 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9416 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9417 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9417 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9418 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
9418 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
| 9419 |
TmpInst.addOperand(Inst.getOperand(6)); |
9419 |
TmpInst.addOperand(Inst.getOperand(6)); |
| 9420 |
Inst = TmpInst; |
9420 |
Inst = TmpInst; |
| 9421 |
return true; |
9421 |
return true; |
| 9422 |
} |
9422 |
} |
| 9423 |
|
9423 |
|
| 9424 |
case ARM::VLD2LNdWB_register_Asm_8: |
9424 |
case ARM::VLD2LNdWB_register_Asm_8: |
| 9425 |
case ARM::VLD2LNdWB_register_Asm_16: |
9425 |
case ARM::VLD2LNdWB_register_Asm_16: |
| 9426 |
case ARM::VLD2LNdWB_register_Asm_32: |
9426 |
case ARM::VLD2LNdWB_register_Asm_32: |
| 9427 |
case ARM::VLD2LNqWB_register_Asm_16: |
9427 |
case ARM::VLD2LNqWB_register_Asm_16: |
| 9428 |
case ARM::VLD2LNqWB_register_Asm_32: { |
9428 |
case ARM::VLD2LNqWB_register_Asm_32: { |
| 9429 |
MCInst TmpInst; |
9429 |
MCInst TmpInst; |
| 9430 |
// Shuffle the operands around so the lane index operand is in the |
9430 |
// Shuffle the operands around so the lane index operand is in the |
| 9431 |
// right place. |
9431 |
// right place. |
| 9432 |
unsigned Spacing; |
9432 |
unsigned Spacing; |
| 9433 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9433 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9434 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9434 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9435 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9435 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9436 |
Spacing)); |
9436 |
Spacing)); |
| 9437 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9437 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9438 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9438 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9439 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9439 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9440 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
9440 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
| 9441 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9441 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9442 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9442 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9443 |
Spacing)); |
9443 |
Spacing)); |
| 9444 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9444 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9445 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
9445 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
| 9446 |
TmpInst.addOperand(Inst.getOperand(6)); |
9446 |
TmpInst.addOperand(Inst.getOperand(6)); |
| 9447 |
Inst = TmpInst; |
9447 |
Inst = TmpInst; |
| 9448 |
return true; |
9448 |
return true; |
| 9449 |
} |
9449 |
} |
| 9450 |
|
9450 |
|
| 9451 |
case ARM::VLD3LNdWB_register_Asm_8: |
9451 |
case ARM::VLD3LNdWB_register_Asm_8: |
| 9452 |
case ARM::VLD3LNdWB_register_Asm_16: |
9452 |
case ARM::VLD3LNdWB_register_Asm_16: |
| 9453 |
case ARM::VLD3LNdWB_register_Asm_32: |
9453 |
case ARM::VLD3LNdWB_register_Asm_32: |
| 9454 |
case ARM::VLD3LNqWB_register_Asm_16: |
9454 |
case ARM::VLD3LNqWB_register_Asm_16: |
| 9455 |
case ARM::VLD3LNqWB_register_Asm_32: { |
9455 |
case ARM::VLD3LNqWB_register_Asm_32: { |
| 9456 |
MCInst TmpInst; |
9456 |
MCInst TmpInst; |
| 9457 |
// Shuffle the operands around so the lane index operand is in the |
9457 |
// Shuffle the operands around so the lane index operand is in the |
| 9458 |
// right place. |
9458 |
// right place. |
| 9459 |
unsigned Spacing; |
9459 |
unsigned Spacing; |
| 9460 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9460 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9461 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9461 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9462 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9462 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9463 |
Spacing)); |
9463 |
Spacing)); |
| 9464 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9464 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9465 |
Spacing * 2)); |
9465 |
Spacing * 2)); |
| 9466 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9466 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9467 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9467 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9468 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9468 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9469 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
9469 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
| 9470 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9470 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9471 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9471 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9472 |
Spacing)); |
9472 |
Spacing)); |
| 9473 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9473 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9474 |
Spacing * 2)); |
9474 |
Spacing * 2)); |
| 9475 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9475 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9476 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
9476 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
| 9477 |
TmpInst.addOperand(Inst.getOperand(6)); |
9477 |
TmpInst.addOperand(Inst.getOperand(6)); |
| 9478 |
Inst = TmpInst; |
9478 |
Inst = TmpInst; |
| 9479 |
return true; |
9479 |
return true; |
| 9480 |
} |
9480 |
} |
| 9481 |
|
9481 |
|
| 9482 |
case ARM::VLD4LNdWB_register_Asm_8: |
9482 |
case ARM::VLD4LNdWB_register_Asm_8: |
| 9483 |
case ARM::VLD4LNdWB_register_Asm_16: |
9483 |
case ARM::VLD4LNdWB_register_Asm_16: |
| 9484 |
case ARM::VLD4LNdWB_register_Asm_32: |
9484 |
case ARM::VLD4LNdWB_register_Asm_32: |
| 9485 |
case ARM::VLD4LNqWB_register_Asm_16: |
9485 |
case ARM::VLD4LNqWB_register_Asm_16: |
| 9486 |
case ARM::VLD4LNqWB_register_Asm_32: { |
9486 |
case ARM::VLD4LNqWB_register_Asm_32: { |
| 9487 |
MCInst TmpInst; |
9487 |
MCInst TmpInst; |
| 9488 |
// Shuffle the operands around so the lane index operand is in the |
9488 |
// Shuffle the operands around so the lane index operand is in the |
| 9489 |
// right place. |
9489 |
// right place. |
| 9490 |
unsigned Spacing; |
9490 |
unsigned Spacing; |
| 9491 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9491 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9492 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9492 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9493 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9493 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9494 |
Spacing)); |
9494 |
Spacing)); |
| 9495 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9495 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9496 |
Spacing * 2)); |
9496 |
Spacing * 2)); |
| 9497 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9497 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9498 |
Spacing * 3)); |
9498 |
Spacing * 3)); |
| 9499 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9499 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9500 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9500 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9501 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9501 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9502 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
9502 |
TmpInst.addOperand(Inst.getOperand(4)); // Rm |
| 9503 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9503 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9504 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9504 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9505 |
Spacing)); |
9505 |
Spacing)); |
| 9506 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9506 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9507 |
Spacing * 2)); |
9507 |
Spacing * 2)); |
| 9508 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9508 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9509 |
Spacing * 3)); |
9509 |
Spacing * 3)); |
| 9510 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9510 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9511 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
9511 |
TmpInst.addOperand(Inst.getOperand(5)); // CondCode |
| 9512 |
TmpInst.addOperand(Inst.getOperand(6)); |
9512 |
TmpInst.addOperand(Inst.getOperand(6)); |
| 9513 |
Inst = TmpInst; |
9513 |
Inst = TmpInst; |
| 9514 |
return true; |
9514 |
return true; |
| 9515 |
} |
9515 |
} |
| 9516 |
|
9516 |
|
| 9517 |
case ARM::VLD1LNdWB_fixed_Asm_8: |
9517 |
case ARM::VLD1LNdWB_fixed_Asm_8: |
| 9518 |
case ARM::VLD1LNdWB_fixed_Asm_16: |
9518 |
case ARM::VLD1LNdWB_fixed_Asm_16: |
| 9519 |
case ARM::VLD1LNdWB_fixed_Asm_32: { |
9519 |
case ARM::VLD1LNdWB_fixed_Asm_32: { |
| 9520 |
MCInst TmpInst; |
9520 |
MCInst TmpInst; |
| 9521 |
// Shuffle the operands around so the lane index operand is in the |
9521 |
// Shuffle the operands around so the lane index operand is in the |
| 9522 |
// right place. |
9522 |
// right place. |
| 9523 |
unsigned Spacing; |
9523 |
unsigned Spacing; |
| 9524 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9524 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9525 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9525 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9526 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9526 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9527 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9527 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9528 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9528 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9529 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9529 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9530 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9530 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9531 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9531 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9532 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9532 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9533 |
TmpInst.addOperand(Inst.getOperand(5)); |
9533 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9534 |
Inst = TmpInst; |
9534 |
Inst = TmpInst; |
| 9535 |
return true; |
9535 |
return true; |
| 9536 |
} |
9536 |
} |
| 9537 |
|
9537 |
|
| 9538 |
case ARM::VLD2LNdWB_fixed_Asm_8: |
9538 |
case ARM::VLD2LNdWB_fixed_Asm_8: |
| 9539 |
case ARM::VLD2LNdWB_fixed_Asm_16: |
9539 |
case ARM::VLD2LNdWB_fixed_Asm_16: |
| 9540 |
case ARM::VLD2LNdWB_fixed_Asm_32: |
9540 |
case ARM::VLD2LNdWB_fixed_Asm_32: |
| 9541 |
case ARM::VLD2LNqWB_fixed_Asm_16: |
9541 |
case ARM::VLD2LNqWB_fixed_Asm_16: |
| 9542 |
case ARM::VLD2LNqWB_fixed_Asm_32: { |
9542 |
case ARM::VLD2LNqWB_fixed_Asm_32: { |
| 9543 |
MCInst TmpInst; |
9543 |
MCInst TmpInst; |
| 9544 |
// Shuffle the operands around so the lane index operand is in the |
9544 |
// Shuffle the operands around so the lane index operand is in the |
| 9545 |
// right place. |
9545 |
// right place. |
| 9546 |
unsigned Spacing; |
9546 |
unsigned Spacing; |
| 9547 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9547 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9548 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9548 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9549 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9549 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9550 |
Spacing)); |
9550 |
Spacing)); |
| 9551 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9551 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9552 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9552 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9553 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9553 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9554 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9554 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9555 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9555 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9556 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9556 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9557 |
Spacing)); |
9557 |
Spacing)); |
| 9558 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9558 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9559 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9559 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9560 |
TmpInst.addOperand(Inst.getOperand(5)); |
9560 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9561 |
Inst = TmpInst; |
9561 |
Inst = TmpInst; |
| 9562 |
return true; |
9562 |
return true; |
| 9563 |
} |
9563 |
} |
| 9564 |
|
9564 |
|
| 9565 |
case ARM::VLD3LNdWB_fixed_Asm_8: |
9565 |
case ARM::VLD3LNdWB_fixed_Asm_8: |
| 9566 |
case ARM::VLD3LNdWB_fixed_Asm_16: |
9566 |
case ARM::VLD3LNdWB_fixed_Asm_16: |
| 9567 |
case ARM::VLD3LNdWB_fixed_Asm_32: |
9567 |
case ARM::VLD3LNdWB_fixed_Asm_32: |
| 9568 |
case ARM::VLD3LNqWB_fixed_Asm_16: |
9568 |
case ARM::VLD3LNqWB_fixed_Asm_16: |
| 9569 |
case ARM::VLD3LNqWB_fixed_Asm_32: { |
9569 |
case ARM::VLD3LNqWB_fixed_Asm_32: { |
| 9570 |
MCInst TmpInst; |
9570 |
MCInst TmpInst; |
| 9571 |
// Shuffle the operands around so the lane index operand is in the |
9571 |
// Shuffle the operands around so the lane index operand is in the |
| 9572 |
// right place. |
9572 |
// right place. |
| 9573 |
unsigned Spacing; |
9573 |
unsigned Spacing; |
| 9574 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9574 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9575 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9575 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9576 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9576 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9577 |
Spacing)); |
9577 |
Spacing)); |
| 9578 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9578 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9579 |
Spacing * 2)); |
9579 |
Spacing * 2)); |
| 9580 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9580 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9581 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9581 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9582 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9582 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9583 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9583 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9584 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9584 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9585 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9585 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9586 |
Spacing)); |
9586 |
Spacing)); |
| 9587 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9587 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9588 |
Spacing * 2)); |
9588 |
Spacing * 2)); |
| 9589 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9589 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9590 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9590 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9591 |
TmpInst.addOperand(Inst.getOperand(5)); |
9591 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9592 |
Inst = TmpInst; |
9592 |
Inst = TmpInst; |
| 9593 |
return true; |
9593 |
return true; |
| 9594 |
} |
9594 |
} |
| 9595 |
|
9595 |
|
| 9596 |
case ARM::VLD4LNdWB_fixed_Asm_8: |
9596 |
case ARM::VLD4LNdWB_fixed_Asm_8: |
| 9597 |
case ARM::VLD4LNdWB_fixed_Asm_16: |
9597 |
case ARM::VLD4LNdWB_fixed_Asm_16: |
| 9598 |
case ARM::VLD4LNdWB_fixed_Asm_32: |
9598 |
case ARM::VLD4LNdWB_fixed_Asm_32: |
| 9599 |
case ARM::VLD4LNqWB_fixed_Asm_16: |
9599 |
case ARM::VLD4LNqWB_fixed_Asm_16: |
| 9600 |
case ARM::VLD4LNqWB_fixed_Asm_32: { |
9600 |
case ARM::VLD4LNqWB_fixed_Asm_32: { |
| 9601 |
MCInst TmpInst; |
9601 |
MCInst TmpInst; |
| 9602 |
// Shuffle the operands around so the lane index operand is in the |
9602 |
// Shuffle the operands around so the lane index operand is in the |
| 9603 |
// right place. |
9603 |
// right place. |
| 9604 |
unsigned Spacing; |
9604 |
unsigned Spacing; |
| 9605 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9605 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9606 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9606 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9607 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9607 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9608 |
Spacing)); |
9608 |
Spacing)); |
| 9609 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9609 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9610 |
Spacing * 2)); |
9610 |
Spacing * 2)); |
| 9611 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9611 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9612 |
Spacing * 3)); |
9612 |
Spacing * 3)); |
| 9613 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
9613 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb |
| 9614 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9614 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9615 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9615 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9616 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9616 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9617 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9617 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9618 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9618 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9619 |
Spacing)); |
9619 |
Spacing)); |
| 9620 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9620 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9621 |
Spacing * 2)); |
9621 |
Spacing * 2)); |
| 9622 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9622 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9623 |
Spacing * 3)); |
9623 |
Spacing * 3)); |
| 9624 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9624 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9625 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9625 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9626 |
TmpInst.addOperand(Inst.getOperand(5)); |
9626 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9627 |
Inst = TmpInst; |
9627 |
Inst = TmpInst; |
| 9628 |
return true; |
9628 |
return true; |
| 9629 |
} |
9629 |
} |
| 9630 |
|
9630 |
|
| 9631 |
case ARM::VLD1LNdAsm_8: |
9631 |
case ARM::VLD1LNdAsm_8: |
| 9632 |
case ARM::VLD1LNdAsm_16: |
9632 |
case ARM::VLD1LNdAsm_16: |
| 9633 |
case ARM::VLD1LNdAsm_32: { |
9633 |
case ARM::VLD1LNdAsm_32: { |
| 9634 |
MCInst TmpInst; |
9634 |
MCInst TmpInst; |
| 9635 |
// Shuffle the operands around so the lane index operand is in the |
9635 |
// Shuffle the operands around so the lane index operand is in the |
| 9636 |
// right place. |
9636 |
// right place. |
| 9637 |
unsigned Spacing; |
9637 |
unsigned Spacing; |
| 9638 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9638 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9639 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9639 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9640 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9640 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9641 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9641 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9642 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9642 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9643 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9643 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9644 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9644 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9645 |
TmpInst.addOperand(Inst.getOperand(5)); |
9645 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9646 |
Inst = TmpInst; |
9646 |
Inst = TmpInst; |
| 9647 |
return true; |
9647 |
return true; |
| 9648 |
} |
9648 |
} |
| 9649 |
|
9649 |
|
| 9650 |
case ARM::VLD2LNdAsm_8: |
9650 |
case ARM::VLD2LNdAsm_8: |
| 9651 |
case ARM::VLD2LNdAsm_16: |
9651 |
case ARM::VLD2LNdAsm_16: |
| 9652 |
case ARM::VLD2LNdAsm_32: |
9652 |
case ARM::VLD2LNdAsm_32: |
| 9653 |
case ARM::VLD2LNqAsm_16: |
9653 |
case ARM::VLD2LNqAsm_16: |
| 9654 |
case ARM::VLD2LNqAsm_32: { |
9654 |
case ARM::VLD2LNqAsm_32: { |
| 9655 |
MCInst TmpInst; |
9655 |
MCInst TmpInst; |
| 9656 |
// Shuffle the operands around so the lane index operand is in the |
9656 |
// Shuffle the operands around so the lane index operand is in the |
| 9657 |
// right place. |
9657 |
// right place. |
| 9658 |
unsigned Spacing; |
9658 |
unsigned Spacing; |
| 9659 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9659 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9660 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9660 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9661 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9661 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9662 |
Spacing)); |
9662 |
Spacing)); |
| 9663 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9663 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9664 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9664 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9665 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9665 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9666 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9666 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9667 |
Spacing)); |
9667 |
Spacing)); |
| 9668 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9668 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9669 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9669 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9670 |
TmpInst.addOperand(Inst.getOperand(5)); |
9670 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9671 |
Inst = TmpInst; |
9671 |
Inst = TmpInst; |
| 9672 |
return true; |
9672 |
return true; |
| 9673 |
} |
9673 |
} |
| 9674 |
|
9674 |
|
| 9675 |
case ARM::VLD3LNdAsm_8: |
9675 |
case ARM::VLD3LNdAsm_8: |
| 9676 |
case ARM::VLD3LNdAsm_16: |
9676 |
case ARM::VLD3LNdAsm_16: |
| 9677 |
case ARM::VLD3LNdAsm_32: |
9677 |
case ARM::VLD3LNdAsm_32: |
| 9678 |
case ARM::VLD3LNqAsm_16: |
9678 |
case ARM::VLD3LNqAsm_16: |
| 9679 |
case ARM::VLD3LNqAsm_32: { |
9679 |
case ARM::VLD3LNqAsm_32: { |
| 9680 |
MCInst TmpInst; |
9680 |
MCInst TmpInst; |
| 9681 |
// Shuffle the operands around so the lane index operand is in the |
9681 |
// Shuffle the operands around so the lane index operand is in the |
| 9682 |
// right place. |
9682 |
// right place. |
| 9683 |
unsigned Spacing; |
9683 |
unsigned Spacing; |
| 9684 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9684 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9685 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9685 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9686 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9686 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9687 |
Spacing)); |
9687 |
Spacing)); |
| 9688 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9688 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9689 |
Spacing * 2)); |
9689 |
Spacing * 2)); |
| 9690 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9690 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9691 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9691 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9692 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9692 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9693 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9693 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9694 |
Spacing)); |
9694 |
Spacing)); |
| 9695 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9695 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9696 |
Spacing * 2)); |
9696 |
Spacing * 2)); |
| 9697 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9697 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9698 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9698 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9699 |
TmpInst.addOperand(Inst.getOperand(5)); |
9699 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9700 |
Inst = TmpInst; |
9700 |
Inst = TmpInst; |
| 9701 |
return true; |
9701 |
return true; |
| 9702 |
} |
9702 |
} |
| 9703 |
|
9703 |
|
| 9704 |
case ARM::VLD4LNdAsm_8: |
9704 |
case ARM::VLD4LNdAsm_8: |
| 9705 |
case ARM::VLD4LNdAsm_16: |
9705 |
case ARM::VLD4LNdAsm_16: |
| 9706 |
case ARM::VLD4LNdAsm_32: |
9706 |
case ARM::VLD4LNdAsm_32: |
| 9707 |
case ARM::VLD4LNqAsm_16: |
9707 |
case ARM::VLD4LNqAsm_16: |
| 9708 |
case ARM::VLD4LNqAsm_32: { |
9708 |
case ARM::VLD4LNqAsm_32: { |
| 9709 |
MCInst TmpInst; |
9709 |
MCInst TmpInst; |
| 9710 |
// Shuffle the operands around so the lane index operand is in the |
9710 |
// Shuffle the operands around so the lane index operand is in the |
| 9711 |
// right place. |
9711 |
// right place. |
| 9712 |
unsigned Spacing; |
9712 |
unsigned Spacing; |
| 9713 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9713 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9714 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9714 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9715 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9715 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9716 |
Spacing)); |
9716 |
Spacing)); |
| 9717 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9717 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9718 |
Spacing * 2)); |
9718 |
Spacing * 2)); |
| 9719 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9719 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9720 |
Spacing * 3)); |
9720 |
Spacing * 3)); |
| 9721 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
9721 |
TmpInst.addOperand(Inst.getOperand(2)); // Rn |
| 9722 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
9722 |
TmpInst.addOperand(Inst.getOperand(3)); // alignment |
| 9723 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
9723 |
TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd) |
| 9724 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9724 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9725 |
Spacing)); |
9725 |
Spacing)); |
| 9726 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9726 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9727 |
Spacing * 2)); |
9727 |
Spacing * 2)); |
| 9728 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9728 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9729 |
Spacing * 3)); |
9729 |
Spacing * 3)); |
| 9730 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
9730 |
TmpInst.addOperand(Inst.getOperand(1)); // lane |
| 9731 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9731 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9732 |
TmpInst.addOperand(Inst.getOperand(5)); |
9732 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9733 |
Inst = TmpInst; |
9733 |
Inst = TmpInst; |
| 9734 |
return true; |
9734 |
return true; |
| 9735 |
} |
9735 |
} |
| 9736 |
|
9736 |
|
| 9737 |
// VLD3DUP single 3-element structure to all lanes instructions. |
9737 |
// VLD3DUP single 3-element structure to all lanes instructions. |
| 9738 |
case ARM::VLD3DUPdAsm_8: |
9738 |
case ARM::VLD3DUPdAsm_8: |
| 9739 |
case ARM::VLD3DUPdAsm_16: |
9739 |
case ARM::VLD3DUPdAsm_16: |
| 9740 |
case ARM::VLD3DUPdAsm_32: |
9740 |
case ARM::VLD3DUPdAsm_32: |
| 9741 |
case ARM::VLD3DUPqAsm_8: |
9741 |
case ARM::VLD3DUPqAsm_8: |
| 9742 |
case ARM::VLD3DUPqAsm_16: |
9742 |
case ARM::VLD3DUPqAsm_16: |
| 9743 |
case ARM::VLD3DUPqAsm_32: { |
9743 |
case ARM::VLD3DUPqAsm_32: { |
| 9744 |
MCInst TmpInst; |
9744 |
MCInst TmpInst; |
| 9745 |
unsigned Spacing; |
9745 |
unsigned Spacing; |
| 9746 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9746 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9747 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9747 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9748 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9748 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9749 |
Spacing)); |
9749 |
Spacing)); |
| 9750 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9750 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9751 |
Spacing * 2)); |
9751 |
Spacing * 2)); |
| 9752 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9752 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9753 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9753 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 9754 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
9754 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 9755 |
TmpInst.addOperand(Inst.getOperand(4)); |
9755 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 9756 |
Inst = TmpInst; |
9756 |
Inst = TmpInst; |
| 9757 |
return true; |
9757 |
return true; |
| 9758 |
} |
9758 |
} |
| 9759 |
|
9759 |
|
| 9760 |
case ARM::VLD3DUPdWB_fixed_Asm_8: |
9760 |
case ARM::VLD3DUPdWB_fixed_Asm_8: |
| 9761 |
case ARM::VLD3DUPdWB_fixed_Asm_16: |
9761 |
case ARM::VLD3DUPdWB_fixed_Asm_16: |
| 9762 |
case ARM::VLD3DUPdWB_fixed_Asm_32: |
9762 |
case ARM::VLD3DUPdWB_fixed_Asm_32: |
| 9763 |
case ARM::VLD3DUPqWB_fixed_Asm_8: |
9763 |
case ARM::VLD3DUPqWB_fixed_Asm_8: |
| 9764 |
case ARM::VLD3DUPqWB_fixed_Asm_16: |
9764 |
case ARM::VLD3DUPqWB_fixed_Asm_16: |
| 9765 |
case ARM::VLD3DUPqWB_fixed_Asm_32: { |
9765 |
case ARM::VLD3DUPqWB_fixed_Asm_32: { |
| 9766 |
MCInst TmpInst; |
9766 |
MCInst TmpInst; |
| 9767 |
unsigned Spacing; |
9767 |
unsigned Spacing; |
| 9768 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9768 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9769 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9769 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9770 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9770 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9771 |
Spacing)); |
9771 |
Spacing)); |
| 9772 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9772 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9773 |
Spacing * 2)); |
9773 |
Spacing * 2)); |
| 9774 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9774 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9775 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
9775 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 9776 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9776 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 9777 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9777 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9778 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
9778 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 9779 |
TmpInst.addOperand(Inst.getOperand(4)); |
9779 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 9780 |
Inst = TmpInst; |
9780 |
Inst = TmpInst; |
| 9781 |
return true; |
9781 |
return true; |
| 9782 |
} |
9782 |
} |
| 9783 |
|
9783 |
|
| 9784 |
case ARM::VLD3DUPdWB_register_Asm_8: |
9784 |
case ARM::VLD3DUPdWB_register_Asm_8: |
| 9785 |
case ARM::VLD3DUPdWB_register_Asm_16: |
9785 |
case ARM::VLD3DUPdWB_register_Asm_16: |
| 9786 |
case ARM::VLD3DUPdWB_register_Asm_32: |
9786 |
case ARM::VLD3DUPdWB_register_Asm_32: |
| 9787 |
case ARM::VLD3DUPqWB_register_Asm_8: |
9787 |
case ARM::VLD3DUPqWB_register_Asm_8: |
| 9788 |
case ARM::VLD3DUPqWB_register_Asm_16: |
9788 |
case ARM::VLD3DUPqWB_register_Asm_16: |
| 9789 |
case ARM::VLD3DUPqWB_register_Asm_32: { |
9789 |
case ARM::VLD3DUPqWB_register_Asm_32: { |
| 9790 |
MCInst TmpInst; |
9790 |
MCInst TmpInst; |
| 9791 |
unsigned Spacing; |
9791 |
unsigned Spacing; |
| 9792 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9792 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9793 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9793 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9794 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9794 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9795 |
Spacing)); |
9795 |
Spacing)); |
| 9796 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9796 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9797 |
Spacing * 2)); |
9797 |
Spacing * 2)); |
| 9798 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9798 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9799 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
9799 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 9800 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9800 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 9801 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
9801 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
| 9802 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9802 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9803 |
TmpInst.addOperand(Inst.getOperand(5)); |
9803 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9804 |
Inst = TmpInst; |
9804 |
Inst = TmpInst; |
| 9805 |
return true; |
9805 |
return true; |
| 9806 |
} |
9806 |
} |
| 9807 |
|
9807 |
|
| 9808 |
// VLD3 multiple 3-element structure instructions. |
9808 |
// VLD3 multiple 3-element structure instructions. |
| 9809 |
case ARM::VLD3dAsm_8: |
9809 |
case ARM::VLD3dAsm_8: |
| 9810 |
case ARM::VLD3dAsm_16: |
9810 |
case ARM::VLD3dAsm_16: |
| 9811 |
case ARM::VLD3dAsm_32: |
9811 |
case ARM::VLD3dAsm_32: |
| 9812 |
case ARM::VLD3qAsm_8: |
9812 |
case ARM::VLD3qAsm_8: |
| 9813 |
case ARM::VLD3qAsm_16: |
9813 |
case ARM::VLD3qAsm_16: |
| 9814 |
case ARM::VLD3qAsm_32: { |
9814 |
case ARM::VLD3qAsm_32: { |
| 9815 |
MCInst TmpInst; |
9815 |
MCInst TmpInst; |
| 9816 |
unsigned Spacing; |
9816 |
unsigned Spacing; |
| 9817 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9817 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9818 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9818 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9819 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9819 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9820 |
Spacing)); |
9820 |
Spacing)); |
| 9821 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9821 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9822 |
Spacing * 2)); |
9822 |
Spacing * 2)); |
| 9823 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9823 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9824 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9824 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 9825 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
9825 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 9826 |
TmpInst.addOperand(Inst.getOperand(4)); |
9826 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 9827 |
Inst = TmpInst; |
9827 |
Inst = TmpInst; |
| 9828 |
return true; |
9828 |
return true; |
| 9829 |
} |
9829 |
} |
| 9830 |
|
9830 |
|
| 9831 |
case ARM::VLD3dWB_fixed_Asm_8: |
9831 |
case ARM::VLD3dWB_fixed_Asm_8: |
| 9832 |
case ARM::VLD3dWB_fixed_Asm_16: |
9832 |
case ARM::VLD3dWB_fixed_Asm_16: |
| 9833 |
case ARM::VLD3dWB_fixed_Asm_32: |
9833 |
case ARM::VLD3dWB_fixed_Asm_32: |
| 9834 |
case ARM::VLD3qWB_fixed_Asm_8: |
9834 |
case ARM::VLD3qWB_fixed_Asm_8: |
| 9835 |
case ARM::VLD3qWB_fixed_Asm_16: |
9835 |
case ARM::VLD3qWB_fixed_Asm_16: |
| 9836 |
case ARM::VLD3qWB_fixed_Asm_32: { |
9836 |
case ARM::VLD3qWB_fixed_Asm_32: { |
| 9837 |
MCInst TmpInst; |
9837 |
MCInst TmpInst; |
| 9838 |
unsigned Spacing; |
9838 |
unsigned Spacing; |
| 9839 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9839 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9840 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9840 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9841 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9841 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9842 |
Spacing)); |
9842 |
Spacing)); |
| 9843 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9843 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9844 |
Spacing * 2)); |
9844 |
Spacing * 2)); |
| 9845 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9845 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9846 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
9846 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 9847 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9847 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 9848 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9848 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9849 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
9849 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 9850 |
TmpInst.addOperand(Inst.getOperand(4)); |
9850 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 9851 |
Inst = TmpInst; |
9851 |
Inst = TmpInst; |
| 9852 |
return true; |
9852 |
return true; |
| 9853 |
} |
9853 |
} |
| 9854 |
|
9854 |
|
| 9855 |
case ARM::VLD3dWB_register_Asm_8: |
9855 |
case ARM::VLD3dWB_register_Asm_8: |
| 9856 |
case ARM::VLD3dWB_register_Asm_16: |
9856 |
case ARM::VLD3dWB_register_Asm_16: |
| 9857 |
case ARM::VLD3dWB_register_Asm_32: |
9857 |
case ARM::VLD3dWB_register_Asm_32: |
| 9858 |
case ARM::VLD3qWB_register_Asm_8: |
9858 |
case ARM::VLD3qWB_register_Asm_8: |
| 9859 |
case ARM::VLD3qWB_register_Asm_16: |
9859 |
case ARM::VLD3qWB_register_Asm_16: |
| 9860 |
case ARM::VLD3qWB_register_Asm_32: { |
9860 |
case ARM::VLD3qWB_register_Asm_32: { |
| 9861 |
MCInst TmpInst; |
9861 |
MCInst TmpInst; |
| 9862 |
unsigned Spacing; |
9862 |
unsigned Spacing; |
| 9863 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9863 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9864 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9864 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9865 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9865 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9866 |
Spacing)); |
9866 |
Spacing)); |
| 9867 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9867 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9868 |
Spacing * 2)); |
9868 |
Spacing * 2)); |
| 9869 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9869 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9870 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
9870 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 9871 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9871 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 9872 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
9872 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
| 9873 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9873 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9874 |
TmpInst.addOperand(Inst.getOperand(5)); |
9874 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9875 |
Inst = TmpInst; |
9875 |
Inst = TmpInst; |
| 9876 |
return true; |
9876 |
return true; |
| 9877 |
} |
9877 |
} |
| 9878 |
|
9878 |
|
| 9879 |
// VLD4DUP single 3-element structure to all lanes instructions. |
9879 |
// VLD4DUP single 3-element structure to all lanes instructions. |
| 9880 |
case ARM::VLD4DUPdAsm_8: |
9880 |
case ARM::VLD4DUPdAsm_8: |
| 9881 |
case ARM::VLD4DUPdAsm_16: |
9881 |
case ARM::VLD4DUPdAsm_16: |
| 9882 |
case ARM::VLD4DUPdAsm_32: |
9882 |
case ARM::VLD4DUPdAsm_32: |
| 9883 |
case ARM::VLD4DUPqAsm_8: |
9883 |
case ARM::VLD4DUPqAsm_8: |
| 9884 |
case ARM::VLD4DUPqAsm_16: |
9884 |
case ARM::VLD4DUPqAsm_16: |
| 9885 |
case ARM::VLD4DUPqAsm_32: { |
9885 |
case ARM::VLD4DUPqAsm_32: { |
| 9886 |
MCInst TmpInst; |
9886 |
MCInst TmpInst; |
| 9887 |
unsigned Spacing; |
9887 |
unsigned Spacing; |
| 9888 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9888 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9889 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9889 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9890 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9890 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9891 |
Spacing)); |
9891 |
Spacing)); |
| 9892 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9892 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9893 |
Spacing * 2)); |
9893 |
Spacing * 2)); |
| 9894 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9894 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9895 |
Spacing * 3)); |
9895 |
Spacing * 3)); |
| 9896 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9896 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9897 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9897 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 9898 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
9898 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 9899 |
TmpInst.addOperand(Inst.getOperand(4)); |
9899 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 9900 |
Inst = TmpInst; |
9900 |
Inst = TmpInst; |
| 9901 |
return true; |
9901 |
return true; |
| 9902 |
} |
9902 |
} |
| 9903 |
|
9903 |
|
| 9904 |
case ARM::VLD4DUPdWB_fixed_Asm_8: |
9904 |
case ARM::VLD4DUPdWB_fixed_Asm_8: |
| 9905 |
case ARM::VLD4DUPdWB_fixed_Asm_16: |
9905 |
case ARM::VLD4DUPdWB_fixed_Asm_16: |
| 9906 |
case ARM::VLD4DUPdWB_fixed_Asm_32: |
9906 |
case ARM::VLD4DUPdWB_fixed_Asm_32: |
| 9907 |
case ARM::VLD4DUPqWB_fixed_Asm_8: |
9907 |
case ARM::VLD4DUPqWB_fixed_Asm_8: |
| 9908 |
case ARM::VLD4DUPqWB_fixed_Asm_16: |
9908 |
case ARM::VLD4DUPqWB_fixed_Asm_16: |
| 9909 |
case ARM::VLD4DUPqWB_fixed_Asm_32: { |
9909 |
case ARM::VLD4DUPqWB_fixed_Asm_32: { |
| 9910 |
MCInst TmpInst; |
9910 |
MCInst TmpInst; |
| 9911 |
unsigned Spacing; |
9911 |
unsigned Spacing; |
| 9912 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9912 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9913 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9913 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9914 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9914 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9915 |
Spacing)); |
9915 |
Spacing)); |
| 9916 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9916 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9917 |
Spacing * 2)); |
9917 |
Spacing * 2)); |
| 9918 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9918 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9919 |
Spacing * 3)); |
9919 |
Spacing * 3)); |
| 9920 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9920 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9921 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
9921 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 9922 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9922 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 9923 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
9923 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 9924 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
9924 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 9925 |
TmpInst.addOperand(Inst.getOperand(4)); |
9925 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 9926 |
Inst = TmpInst; |
9926 |
Inst = TmpInst; |
| 9927 |
return true; |
9927 |
return true; |
| 9928 |
} |
9928 |
} |
| 9929 |
|
9929 |
|
| 9930 |
case ARM::VLD4DUPdWB_register_Asm_8: |
9930 |
case ARM::VLD4DUPdWB_register_Asm_8: |
| 9931 |
case ARM::VLD4DUPdWB_register_Asm_16: |
9931 |
case ARM::VLD4DUPdWB_register_Asm_16: |
| 9932 |
case ARM::VLD4DUPdWB_register_Asm_32: |
9932 |
case ARM::VLD4DUPdWB_register_Asm_32: |
| 9933 |
case ARM::VLD4DUPqWB_register_Asm_8: |
9933 |
case ARM::VLD4DUPqWB_register_Asm_8: |
| 9934 |
case ARM::VLD4DUPqWB_register_Asm_16: |
9934 |
case ARM::VLD4DUPqWB_register_Asm_16: |
| 9935 |
case ARM::VLD4DUPqWB_register_Asm_32: { |
9935 |
case ARM::VLD4DUPqWB_register_Asm_32: { |
| 9936 |
MCInst TmpInst; |
9936 |
MCInst TmpInst; |
| 9937 |
unsigned Spacing; |
9937 |
unsigned Spacing; |
| 9938 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9938 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9939 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9939 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9940 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9940 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9941 |
Spacing)); |
9941 |
Spacing)); |
| 9942 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9942 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9943 |
Spacing * 2)); |
9943 |
Spacing * 2)); |
| 9944 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9944 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9945 |
Spacing * 3)); |
9945 |
Spacing * 3)); |
| 9946 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9946 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9947 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
9947 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 9948 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9948 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 9949 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
9949 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
| 9950 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
9950 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 9951 |
TmpInst.addOperand(Inst.getOperand(5)); |
9951 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 9952 |
Inst = TmpInst; |
9952 |
Inst = TmpInst; |
| 9953 |
return true; |
9953 |
return true; |
| 9954 |
} |
9954 |
} |
| 9955 |
|
9955 |
|
| 9956 |
// VLD4 multiple 4-element structure instructions. |
9956 |
// VLD4 multiple 4-element structure instructions. |
| 9957 |
case ARM::VLD4dAsm_8: |
9957 |
case ARM::VLD4dAsm_8: |
| 9958 |
case ARM::VLD4dAsm_16: |
9958 |
case ARM::VLD4dAsm_16: |
| 9959 |
case ARM::VLD4dAsm_32: |
9959 |
case ARM::VLD4dAsm_32: |
| 9960 |
case ARM::VLD4qAsm_8: |
9960 |
case ARM::VLD4qAsm_8: |
| 9961 |
case ARM::VLD4qAsm_16: |
9961 |
case ARM::VLD4qAsm_16: |
| 9962 |
case ARM::VLD4qAsm_32: { |
9962 |
case ARM::VLD4qAsm_32: { |
| 9963 |
MCInst TmpInst; |
9963 |
MCInst TmpInst; |
| 9964 |
unsigned Spacing; |
9964 |
unsigned Spacing; |
| 9965 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9965 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9966 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9966 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9967 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9967 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9968 |
Spacing)); |
9968 |
Spacing)); |
| 9969 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9969 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9970 |
Spacing * 2)); |
9970 |
Spacing * 2)); |
| 9971 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9971 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9972 |
Spacing * 3)); |
9972 |
Spacing * 3)); |
| 9973 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9973 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9974 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9974 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 9975 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
9975 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 9976 |
TmpInst.addOperand(Inst.getOperand(4)); |
9976 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 9977 |
Inst = TmpInst; |
9977 |
Inst = TmpInst; |
| 9978 |
return true; |
9978 |
return true; |
| 9979 |
} |
9979 |
} |
| 9980 |
|
9980 |
|
| 9981 |
case ARM::VLD4dWB_fixed_Asm_8: |
9981 |
case ARM::VLD4dWB_fixed_Asm_8: |
| 9982 |
case ARM::VLD4dWB_fixed_Asm_16: |
9982 |
case ARM::VLD4dWB_fixed_Asm_16: |
| 9983 |
case ARM::VLD4dWB_fixed_Asm_32: |
9983 |
case ARM::VLD4dWB_fixed_Asm_32: |
| 9984 |
case ARM::VLD4qWB_fixed_Asm_8: |
9984 |
case ARM::VLD4qWB_fixed_Asm_8: |
| 9985 |
case ARM::VLD4qWB_fixed_Asm_16: |
9985 |
case ARM::VLD4qWB_fixed_Asm_16: |
| 9986 |
case ARM::VLD4qWB_fixed_Asm_32: { |
9986 |
case ARM::VLD4qWB_fixed_Asm_32: { |
| 9987 |
MCInst TmpInst; |
9987 |
MCInst TmpInst; |
| 9988 |
unsigned Spacing; |
9988 |
unsigned Spacing; |
| 9989 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
9989 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 9990 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
9990 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 9991 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9991 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9992 |
Spacing)); |
9992 |
Spacing)); |
| 9993 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9993 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9994 |
Spacing * 2)); |
9994 |
Spacing * 2)); |
| 9995 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
9995 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 9996 |
Spacing * 3)); |
9996 |
Spacing * 3)); |
| 9997 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
9997 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 9998 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
9998 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 9999 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
9999 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 10000 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
10000 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 10001 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
10001 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 10002 |
TmpInst.addOperand(Inst.getOperand(4)); |
10002 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10003 |
Inst = TmpInst; |
10003 |
Inst = TmpInst; |
| 10004 |
return true; |
10004 |
return true; |
| 10005 |
} |
10005 |
} |
| 10006 |
|
10006 |
|
| 10007 |
case ARM::VLD4dWB_register_Asm_8: |
10007 |
case ARM::VLD4dWB_register_Asm_8: |
| 10008 |
case ARM::VLD4dWB_register_Asm_16: |
10008 |
case ARM::VLD4dWB_register_Asm_16: |
| 10009 |
case ARM::VLD4dWB_register_Asm_32: |
10009 |
case ARM::VLD4dWB_register_Asm_32: |
| 10010 |
case ARM::VLD4qWB_register_Asm_8: |
10010 |
case ARM::VLD4qWB_register_Asm_8: |
| 10011 |
case ARM::VLD4qWB_register_Asm_16: |
10011 |
case ARM::VLD4qWB_register_Asm_16: |
| 10012 |
case ARM::VLD4qWB_register_Asm_32: { |
10012 |
case ARM::VLD4qWB_register_Asm_32: { |
| 10013 |
MCInst TmpInst; |
10013 |
MCInst TmpInst; |
| 10014 |
unsigned Spacing; |
10014 |
unsigned Spacing; |
| 10015 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
10015 |
TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing)); |
| 10016 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
10016 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 10017 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10017 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10018 |
Spacing)); |
10018 |
Spacing)); |
| 10019 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10019 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10020 |
Spacing * 2)); |
10020 |
Spacing * 2)); |
| 10021 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10021 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10022 |
Spacing * 3)); |
10022 |
Spacing * 3)); |
| 10023 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10023 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10024 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
10024 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 10025 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
10025 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 10026 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
10026 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
| 10027 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
10027 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 10028 |
TmpInst.addOperand(Inst.getOperand(5)); |
10028 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 10029 |
Inst = TmpInst; |
10029 |
Inst = TmpInst; |
| 10030 |
return true; |
10030 |
return true; |
| 10031 |
} |
10031 |
} |
| 10032 |
|
10032 |
|
| 10033 |
// VST3 multiple 3-element structure instructions. |
10033 |
// VST3 multiple 3-element structure instructions. |
| 10034 |
case ARM::VST3dAsm_8: |
10034 |
case ARM::VST3dAsm_8: |
| 10035 |
case ARM::VST3dAsm_16: |
10035 |
case ARM::VST3dAsm_16: |
| 10036 |
case ARM::VST3dAsm_32: |
10036 |
case ARM::VST3dAsm_32: |
| 10037 |
case ARM::VST3qAsm_8: |
10037 |
case ARM::VST3qAsm_8: |
| 10038 |
case ARM::VST3qAsm_16: |
10038 |
case ARM::VST3qAsm_16: |
| 10039 |
case ARM::VST3qAsm_32: { |
10039 |
case ARM::VST3qAsm_32: { |
| 10040 |
MCInst TmpInst; |
10040 |
MCInst TmpInst; |
| 10041 |
unsigned Spacing; |
10041 |
unsigned Spacing; |
| 10042 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
10042 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 10043 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10043 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10044 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
10044 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 10045 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
10045 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 10046 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10046 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10047 |
Spacing)); |
10047 |
Spacing)); |
| 10048 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10048 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10049 |
Spacing * 2)); |
10049 |
Spacing * 2)); |
| 10050 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
10050 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 10051 |
TmpInst.addOperand(Inst.getOperand(4)); |
10051 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10052 |
Inst = TmpInst; |
10052 |
Inst = TmpInst; |
| 10053 |
return true; |
10053 |
return true; |
| 10054 |
} |
10054 |
} |
| 10055 |
|
10055 |
|
| 10056 |
case ARM::VST3dWB_fixed_Asm_8: |
10056 |
case ARM::VST3dWB_fixed_Asm_8: |
| 10057 |
case ARM::VST3dWB_fixed_Asm_16: |
10057 |
case ARM::VST3dWB_fixed_Asm_16: |
| 10058 |
case ARM::VST3dWB_fixed_Asm_32: |
10058 |
case ARM::VST3dWB_fixed_Asm_32: |
| 10059 |
case ARM::VST3qWB_fixed_Asm_8: |
10059 |
case ARM::VST3qWB_fixed_Asm_8: |
| 10060 |
case ARM::VST3qWB_fixed_Asm_16: |
10060 |
case ARM::VST3qWB_fixed_Asm_16: |
| 10061 |
case ARM::VST3qWB_fixed_Asm_32: { |
10061 |
case ARM::VST3qWB_fixed_Asm_32: { |
| 10062 |
MCInst TmpInst; |
10062 |
MCInst TmpInst; |
| 10063 |
unsigned Spacing; |
10063 |
unsigned Spacing; |
| 10064 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
10064 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 10065 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10065 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10066 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
10066 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 10067 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
10067 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 10068 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
10068 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 10069 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
10069 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 10070 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10070 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10071 |
Spacing)); |
10071 |
Spacing)); |
| 10072 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10072 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10073 |
Spacing * 2)); |
10073 |
Spacing * 2)); |
| 10074 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
10074 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 10075 |
TmpInst.addOperand(Inst.getOperand(4)); |
10075 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10076 |
Inst = TmpInst; |
10076 |
Inst = TmpInst; |
| 10077 |
return true; |
10077 |
return true; |
| 10078 |
} |
10078 |
} |
| 10079 |
|
10079 |
|
| 10080 |
case ARM::VST3dWB_register_Asm_8: |
10080 |
case ARM::VST3dWB_register_Asm_8: |
| 10081 |
case ARM::VST3dWB_register_Asm_16: |
10081 |
case ARM::VST3dWB_register_Asm_16: |
| 10082 |
case ARM::VST3dWB_register_Asm_32: |
10082 |
case ARM::VST3dWB_register_Asm_32: |
| 10083 |
case ARM::VST3qWB_register_Asm_8: |
10083 |
case ARM::VST3qWB_register_Asm_8: |
| 10084 |
case ARM::VST3qWB_register_Asm_16: |
10084 |
case ARM::VST3qWB_register_Asm_16: |
| 10085 |
case ARM::VST3qWB_register_Asm_32: { |
10085 |
case ARM::VST3qWB_register_Asm_32: { |
| 10086 |
MCInst TmpInst; |
10086 |
MCInst TmpInst; |
| 10087 |
unsigned Spacing; |
10087 |
unsigned Spacing; |
| 10088 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
10088 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 10089 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10089 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10090 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
10090 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 10091 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
10091 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 10092 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
10092 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
| 10093 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
10093 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 10094 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10094 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10095 |
Spacing)); |
10095 |
Spacing)); |
| 10096 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10096 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10097 |
Spacing * 2)); |
10097 |
Spacing * 2)); |
| 10098 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
10098 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 10099 |
TmpInst.addOperand(Inst.getOperand(5)); |
10099 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 10100 |
Inst = TmpInst; |
10100 |
Inst = TmpInst; |
| 10101 |
return true; |
10101 |
return true; |
| 10102 |
} |
10102 |
} |
| 10103 |
|
10103 |
|
| 10104 |
// VST4 multiple 3-element structure instructions. |
10104 |
// VST4 multiple 3-element structure instructions. |
| 10105 |
case ARM::VST4dAsm_8: |
10105 |
case ARM::VST4dAsm_8: |
| 10106 |
case ARM::VST4dAsm_16: |
10106 |
case ARM::VST4dAsm_16: |
| 10107 |
case ARM::VST4dAsm_32: |
10107 |
case ARM::VST4dAsm_32: |
| 10108 |
case ARM::VST4qAsm_8: |
10108 |
case ARM::VST4qAsm_8: |
| 10109 |
case ARM::VST4qAsm_16: |
10109 |
case ARM::VST4qAsm_16: |
| 10110 |
case ARM::VST4qAsm_32: { |
10110 |
case ARM::VST4qAsm_32: { |
| 10111 |
MCInst TmpInst; |
10111 |
MCInst TmpInst; |
| 10112 |
unsigned Spacing; |
10112 |
unsigned Spacing; |
| 10113 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
10113 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 10114 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10114 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10115 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
10115 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 10116 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
10116 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 10117 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10117 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10118 |
Spacing)); |
10118 |
Spacing)); |
| 10119 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10119 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10120 |
Spacing * 2)); |
10120 |
Spacing * 2)); |
| 10121 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10121 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10122 |
Spacing * 3)); |
10122 |
Spacing * 3)); |
| 10123 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
10123 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 10124 |
TmpInst.addOperand(Inst.getOperand(4)); |
10124 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10125 |
Inst = TmpInst; |
10125 |
Inst = TmpInst; |
| 10126 |
return true; |
10126 |
return true; |
| 10127 |
} |
10127 |
} |
| 10128 |
|
10128 |
|
| 10129 |
case ARM::VST4dWB_fixed_Asm_8: |
10129 |
case ARM::VST4dWB_fixed_Asm_8: |
| 10130 |
case ARM::VST4dWB_fixed_Asm_16: |
10130 |
case ARM::VST4dWB_fixed_Asm_16: |
| 10131 |
case ARM::VST4dWB_fixed_Asm_32: |
10131 |
case ARM::VST4dWB_fixed_Asm_32: |
| 10132 |
case ARM::VST4qWB_fixed_Asm_8: |
10132 |
case ARM::VST4qWB_fixed_Asm_8: |
| 10133 |
case ARM::VST4qWB_fixed_Asm_16: |
10133 |
case ARM::VST4qWB_fixed_Asm_16: |
| 10134 |
case ARM::VST4qWB_fixed_Asm_32: { |
10134 |
case ARM::VST4qWB_fixed_Asm_32: { |
| 10135 |
MCInst TmpInst; |
10135 |
MCInst TmpInst; |
| 10136 |
unsigned Spacing; |
10136 |
unsigned Spacing; |
| 10137 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
10137 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 10138 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10138 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10139 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
10139 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 10140 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
10140 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 10141 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
10141 |
TmpInst.addOperand(MCOperand::createReg(0)); // Rm |
| 10142 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
10142 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 10143 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10143 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10144 |
Spacing)); |
10144 |
Spacing)); |
| 10145 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10145 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10146 |
Spacing * 2)); |
10146 |
Spacing * 2)); |
| 10147 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10147 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10148 |
Spacing * 3)); |
10148 |
Spacing * 3)); |
| 10149 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
10149 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 10150 |
TmpInst.addOperand(Inst.getOperand(4)); |
10150 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10151 |
Inst = TmpInst; |
10151 |
Inst = TmpInst; |
| 10152 |
return true; |
10152 |
return true; |
| 10153 |
} |
10153 |
} |
| 10154 |
|
10154 |
|
| 10155 |
case ARM::VST4dWB_register_Asm_8: |
10155 |
case ARM::VST4dWB_register_Asm_8: |
| 10156 |
case ARM::VST4dWB_register_Asm_16: |
10156 |
case ARM::VST4dWB_register_Asm_16: |
| 10157 |
case ARM::VST4dWB_register_Asm_32: |
10157 |
case ARM::VST4dWB_register_Asm_32: |
| 10158 |
case ARM::VST4qWB_register_Asm_8: |
10158 |
case ARM::VST4qWB_register_Asm_8: |
| 10159 |
case ARM::VST4qWB_register_Asm_16: |
10159 |
case ARM::VST4qWB_register_Asm_16: |
| 10160 |
case ARM::VST4qWB_register_Asm_32: { |
10160 |
case ARM::VST4qWB_register_Asm_32: { |
| 10161 |
MCInst TmpInst; |
10161 |
MCInst TmpInst; |
| 10162 |
unsigned Spacing; |
10162 |
unsigned Spacing; |
| 10163 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
10163 |
TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing)); |
| 10164 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10164 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10165 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
10165 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn |
| 10166 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
10166 |
TmpInst.addOperand(Inst.getOperand(2)); // alignment |
| 10167 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
10167 |
TmpInst.addOperand(Inst.getOperand(3)); // Rm |
| 10168 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
10168 |
TmpInst.addOperand(Inst.getOperand(0)); // Vd |
| 10169 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10169 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10170 |
Spacing)); |
10170 |
Spacing)); |
| 10171 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10171 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10172 |
Spacing * 2)); |
10172 |
Spacing * 2)); |
| 10173 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
10173 |
TmpInst.addOperand(MCOperand::createReg(Inst.getOperand(0).getReg() + |
| 10174 |
Spacing * 3)); |
10174 |
Spacing * 3)); |
| 10175 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
10175 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 10176 |
TmpInst.addOperand(Inst.getOperand(5)); |
10176 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 10177 |
Inst = TmpInst; |
10177 |
Inst = TmpInst; |
| 10178 |
return true; |
10178 |
return true; |
| 10179 |
} |
10179 |
} |
| 10180 |
|
10180 |
|
| 10181 |
// Handle encoding choice for the shift-immediate instructions. |
10181 |
// Handle encoding choice for the shift-immediate instructions. |
| 10182 |
case ARM::t2LSLri: |
10182 |
case ARM::t2LSLri: |
| 10183 |
case ARM::t2LSRri: |
10183 |
case ARM::t2LSRri: |
| 10184 |
case ARM::t2ASRri: |
10184 |
case ARM::t2ASRri: |
| 10185 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
10185 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
| 10186 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
10186 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
| 10187 |
Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) && |
10187 |
Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) && |
| 10188 |
!HasWideQualifier) { |
10188 |
!HasWideQualifier) { |
| 10189 |
unsigned NewOpc; |
10189 |
unsigned NewOpc; |
| 10190 |
switch (Inst.getOpcode()) { |
10190 |
switch (Inst.getOpcode()) { |
| 10191 |
default: llvm_unreachable("unexpected opcode"); |
10191 |
default: llvm_unreachable("unexpected opcode"); |
| 10192 |
case ARM::t2LSLri: NewOpc = ARM::tLSLri; break; |
10192 |
case ARM::t2LSLri: NewOpc = ARM::tLSLri; break; |
| 10193 |
case ARM::t2LSRri: NewOpc = ARM::tLSRri; break; |
10193 |
case ARM::t2LSRri: NewOpc = ARM::tLSRri; break; |
| 10194 |
case ARM::t2ASRri: NewOpc = ARM::tASRri; break; |
10194 |
case ARM::t2ASRri: NewOpc = ARM::tASRri; break; |
| 10195 |
} |
10195 |
} |
| 10196 |
// The Thumb1 operands aren't in the same order. Awesome, eh? |
10196 |
// The Thumb1 operands aren't in the same order. Awesome, eh? |
| 10197 |
MCInst TmpInst; |
10197 |
MCInst TmpInst; |
| 10198 |
TmpInst.setOpcode(NewOpc); |
10198 |
TmpInst.setOpcode(NewOpc); |
| 10199 |
TmpInst.addOperand(Inst.getOperand(0)); |
10199 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10200 |
TmpInst.addOperand(Inst.getOperand(5)); |
10200 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 10201 |
TmpInst.addOperand(Inst.getOperand(1)); |
10201 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 10202 |
TmpInst.addOperand(Inst.getOperand(2)); |
10202 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 10203 |
TmpInst.addOperand(Inst.getOperand(3)); |
10203 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10204 |
TmpInst.addOperand(Inst.getOperand(4)); |
10204 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10205 |
Inst = TmpInst; |
10205 |
Inst = TmpInst; |
| 10206 |
return true; |
10206 |
return true; |
| 10207 |
} |
10207 |
} |
| 10208 |
return false; |
10208 |
return false; |
| 10209 |
|
10209 |
|
| 10210 |
// Handle the Thumb2 mode MOV complex aliases. |
10210 |
// Handle the Thumb2 mode MOV complex aliases. |
| 10211 |
case ARM::t2MOVsr: |
10211 |
case ARM::t2MOVsr: |
| 10212 |
case ARM::t2MOVSsr: { |
10212 |
case ARM::t2MOVSsr: { |
| 10213 |
// Which instruction to expand to depends on the CCOut operand and |
10213 |
// Which instruction to expand to depends on the CCOut operand and |
| 10214 |
// whether we're in an IT block if the register operands are low |
10214 |
// whether we're in an IT block if the register operands are low |
| 10215 |
// registers. |
10215 |
// registers. |
| 10216 |
bool isNarrow = false; |
10216 |
bool isNarrow = false; |
| 10217 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
10217 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
| 10218 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
10218 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
| 10219 |
isARMLowRegister(Inst.getOperand(2).getReg()) && |
10219 |
isARMLowRegister(Inst.getOperand(2).getReg()) && |
| 10220 |
Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && |
10220 |
Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && |
| 10221 |
inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr) && |
10221 |
inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr) && |
| 10222 |
!HasWideQualifier) |
10222 |
!HasWideQualifier) |
| 10223 |
isNarrow = true; |
10223 |
isNarrow = true; |
| 10224 |
MCInst TmpInst; |
10224 |
MCInst TmpInst; |
| 10225 |
unsigned newOpc; |
10225 |
unsigned newOpc; |
| 10226 |
switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) { |
10226 |
switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) { |
| 10227 |
default: llvm_unreachable("unexpected opcode!"); |
10227 |
default: llvm_unreachable("unexpected opcode!"); |
| 10228 |
case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break; |
10228 |
case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break; |
| 10229 |
case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break; |
10229 |
case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break; |
| 10230 |
case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break; |
10230 |
case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break; |
| 10231 |
case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break; |
10231 |
case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break; |
| 10232 |
} |
10232 |
} |
| 10233 |
TmpInst.setOpcode(newOpc); |
10233 |
TmpInst.setOpcode(newOpc); |
| 10234 |
TmpInst.addOperand(Inst.getOperand(0)); // Rd |
10234 |
TmpInst.addOperand(Inst.getOperand(0)); // Rd |
| 10235 |
if (isNarrow) |
10235 |
if (isNarrow) |
| 10236 |
TmpInst.addOperand(MCOperand::createReg( |
10236 |
TmpInst.addOperand(MCOperand::createReg( |
| 10237 |
Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0)); |
10237 |
Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0)); |
| 10238 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10238 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10239 |
TmpInst.addOperand(Inst.getOperand(2)); // Rm |
10239 |
TmpInst.addOperand(Inst.getOperand(2)); // Rm |
| 10240 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
10240 |
TmpInst.addOperand(Inst.getOperand(4)); // CondCode |
| 10241 |
TmpInst.addOperand(Inst.getOperand(5)); |
10241 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 10242 |
if (!isNarrow) |
10242 |
if (!isNarrow) |
| 10243 |
TmpInst.addOperand(MCOperand::createReg( |
10243 |
TmpInst.addOperand(MCOperand::createReg( |
| 10244 |
Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0)); |
10244 |
Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0)); |
| 10245 |
Inst = TmpInst; |
10245 |
Inst = TmpInst; |
| 10246 |
return true; |
10246 |
return true; |
| 10247 |
} |
10247 |
} |
| 10248 |
case ARM::t2MOVsi: |
10248 |
case ARM::t2MOVsi: |
| 10249 |
case ARM::t2MOVSsi: { |
10249 |
case ARM::t2MOVSsi: { |
| 10250 |
// Which instruction to expand to depends on the CCOut operand and |
10250 |
// Which instruction to expand to depends on the CCOut operand and |
| 10251 |
// whether we're in an IT block if the register operands are low |
10251 |
// whether we're in an IT block if the register operands are low |
| 10252 |
// registers. |
10252 |
// registers. |
| 10253 |
bool isNarrow = false; |
10253 |
bool isNarrow = false; |
| 10254 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
10254 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
| 10255 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
10255 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
| 10256 |
inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi) && |
10256 |
inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi) && |
| 10257 |
!HasWideQualifier) |
10257 |
!HasWideQualifier) |
| 10258 |
isNarrow = true; |
10258 |
isNarrow = true; |
| 10259 |
MCInst TmpInst; |
10259 |
MCInst TmpInst; |
| 10260 |
unsigned newOpc; |
10260 |
unsigned newOpc; |
| 10261 |
unsigned Shift = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm()); |
10261 |
unsigned Shift = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm()); |
| 10262 |
unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()); |
10262 |
unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()); |
| 10263 |
bool isMov = false; |
10263 |
bool isMov = false; |
| 10264 |
// MOV rd, rm, LSL #0 is actually a MOV instruction |
10264 |
// MOV rd, rm, LSL #0 is actually a MOV instruction |
| 10265 |
if (Shift == ARM_AM::lsl && Amount == 0) { |
10265 |
if (Shift == ARM_AM::lsl && Amount == 0) { |
| 10266 |
isMov = true; |
10266 |
isMov = true; |
| 10267 |
// The 16-bit encoding of MOV rd, rm, LSL #N is explicitly encoding T2 of |
10267 |
// The 16-bit encoding of MOV rd, rm, LSL #N is explicitly encoding T2 of |
| 10268 |
// MOV (register) in the ARMv8-A and ARMv8-M manuals, and immediate 0 is |
10268 |
// MOV (register) in the ARMv8-A and ARMv8-M manuals, and immediate 0 is |
| 10269 |
// unpredictable in an IT block so the 32-bit encoding T3 has to be used |
10269 |
// unpredictable in an IT block so the 32-bit encoding T3 has to be used |
| 10270 |
// instead. |
10270 |
// instead. |
| 10271 |
if (inITBlock()) { |
10271 |
if (inITBlock()) { |
| 10272 |
isNarrow = false; |
10272 |
isNarrow = false; |
| 10273 |
} |
10273 |
} |
| 10274 |
newOpc = isNarrow ? ARM::tMOVSr : ARM::t2MOVr; |
10274 |
newOpc = isNarrow ? ARM::tMOVSr : ARM::t2MOVr; |
| 10275 |
} else { |
10275 |
} else { |
| 10276 |
switch(Shift) { |
10276 |
switch(Shift) { |
| 10277 |
default: llvm_unreachable("unexpected opcode!"); |
10277 |
default: llvm_unreachable("unexpected opcode!"); |
| 10278 |
case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break; |
10278 |
case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break; |
| 10279 |
case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break; |
10279 |
case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break; |
| 10280 |
case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break; |
10280 |
case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break; |
| 10281 |
case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break; |
10281 |
case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break; |
| 10282 |
case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break; |
10282 |
case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break; |
| 10283 |
} |
10283 |
} |
| 10284 |
} |
10284 |
} |
| 10285 |
if (Amount == 32) Amount = 0; |
10285 |
if (Amount == 32) Amount = 0; |
| 10286 |
TmpInst.setOpcode(newOpc); |
10286 |
TmpInst.setOpcode(newOpc); |
| 10287 |
TmpInst.addOperand(Inst.getOperand(0)); // Rd |
10287 |
TmpInst.addOperand(Inst.getOperand(0)); // Rd |
| 10288 |
if (isNarrow && !isMov) |
10288 |
if (isNarrow && !isMov) |
| 10289 |
TmpInst.addOperand(MCOperand::createReg( |
10289 |
TmpInst.addOperand(MCOperand::createReg( |
| 10290 |
Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); |
10290 |
Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); |
| 10291 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10291 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10292 |
if (newOpc != ARM::t2RRX && !isMov) |
10292 |
if (newOpc != ARM::t2RRX && !isMov) |
| 10293 |
TmpInst.addOperand(MCOperand::createImm(Amount)); |
10293 |
TmpInst.addOperand(MCOperand::createImm(Amount)); |
| 10294 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
10294 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 10295 |
TmpInst.addOperand(Inst.getOperand(4)); |
10295 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10296 |
if (!isNarrow) |
10296 |
if (!isNarrow) |
| 10297 |
TmpInst.addOperand(MCOperand::createReg( |
10297 |
TmpInst.addOperand(MCOperand::createReg( |
| 10298 |
Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); |
10298 |
Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0)); |
| 10299 |
Inst = TmpInst; |
10299 |
Inst = TmpInst; |
| 10300 |
return true; |
10300 |
return true; |
| 10301 |
} |
10301 |
} |
| 10302 |
// Handle the ARM mode MOV complex aliases. |
10302 |
// Handle the ARM mode MOV complex aliases. |
| 10303 |
case ARM::ASRr: |
10303 |
case ARM::ASRr: |
| 10304 |
case ARM::LSRr: |
10304 |
case ARM::LSRr: |
| 10305 |
case ARM::LSLr: |
10305 |
case ARM::LSLr: |
| 10306 |
case ARM::RORr: { |
10306 |
case ARM::RORr: { |
| 10307 |
ARM_AM::ShiftOpc ShiftTy; |
10307 |
ARM_AM::ShiftOpc ShiftTy; |
| 10308 |
switch(Inst.getOpcode()) { |
10308 |
switch(Inst.getOpcode()) { |
| 10309 |
default: llvm_unreachable("unexpected opcode!"); |
10309 |
default: llvm_unreachable("unexpected opcode!"); |
| 10310 |
case ARM::ASRr: ShiftTy = ARM_AM::asr; break; |
10310 |
case ARM::ASRr: ShiftTy = ARM_AM::asr; break; |
| 10311 |
case ARM::LSRr: ShiftTy = ARM_AM::lsr; break; |
10311 |
case ARM::LSRr: ShiftTy = ARM_AM::lsr; break; |
| 10312 |
case ARM::LSLr: ShiftTy = ARM_AM::lsl; break; |
10312 |
case ARM::LSLr: ShiftTy = ARM_AM::lsl; break; |
| 10313 |
case ARM::RORr: ShiftTy = ARM_AM::ror; break; |
10313 |
case ARM::RORr: ShiftTy = ARM_AM::ror; break; |
| 10314 |
} |
10314 |
} |
| 10315 |
unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0); |
10315 |
unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0); |
| 10316 |
MCInst TmpInst; |
10316 |
MCInst TmpInst; |
| 10317 |
TmpInst.setOpcode(ARM::MOVsr); |
10317 |
TmpInst.setOpcode(ARM::MOVsr); |
| 10318 |
TmpInst.addOperand(Inst.getOperand(0)); // Rd |
10318 |
TmpInst.addOperand(Inst.getOperand(0)); // Rd |
| 10319 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10319 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10320 |
TmpInst.addOperand(Inst.getOperand(2)); // Rm |
10320 |
TmpInst.addOperand(Inst.getOperand(2)); // Rm |
| 10321 |
TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty |
10321 |
TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty |
| 10322 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
10322 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 10323 |
TmpInst.addOperand(Inst.getOperand(4)); |
10323 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10324 |
TmpInst.addOperand(Inst.getOperand(5)); // cc_out |
10324 |
TmpInst.addOperand(Inst.getOperand(5)); // cc_out |
| 10325 |
Inst = TmpInst; |
10325 |
Inst = TmpInst; |
| 10326 |
return true; |
10326 |
return true; |
| 10327 |
} |
10327 |
} |
| 10328 |
case ARM::ASRi: |
10328 |
case ARM::ASRi: |
| 10329 |
case ARM::LSRi: |
10329 |
case ARM::LSRi: |
| 10330 |
case ARM::LSLi: |
10330 |
case ARM::LSLi: |
| 10331 |
case ARM::RORi: { |
10331 |
case ARM::RORi: { |
| 10332 |
ARM_AM::ShiftOpc ShiftTy; |
10332 |
ARM_AM::ShiftOpc ShiftTy; |
| 10333 |
switch(Inst.getOpcode()) { |
10333 |
switch(Inst.getOpcode()) { |
| 10334 |
default: llvm_unreachable("unexpected opcode!"); |
10334 |
default: llvm_unreachable("unexpected opcode!"); |
| 10335 |
case ARM::ASRi: ShiftTy = ARM_AM::asr; break; |
10335 |
case ARM::ASRi: ShiftTy = ARM_AM::asr; break; |
| 10336 |
case ARM::LSRi: ShiftTy = ARM_AM::lsr; break; |
10336 |
case ARM::LSRi: ShiftTy = ARM_AM::lsr; break; |
| 10337 |
case ARM::LSLi: ShiftTy = ARM_AM::lsl; break; |
10337 |
case ARM::LSLi: ShiftTy = ARM_AM::lsl; break; |
| 10338 |
case ARM::RORi: ShiftTy = ARM_AM::ror; break; |
10338 |
case ARM::RORi: ShiftTy = ARM_AM::ror; break; |
| 10339 |
} |
10339 |
} |
| 10340 |
// A shift by zero is a plain MOVr, not a MOVsi. |
10340 |
// A shift by zero is a plain MOVr, not a MOVsi. |
| 10341 |
unsigned Amt = Inst.getOperand(2).getImm(); |
10341 |
unsigned Amt = Inst.getOperand(2).getImm(); |
| 10342 |
unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi; |
10342 |
unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi; |
| 10343 |
// A shift by 32 should be encoded as 0 when permitted |
10343 |
// A shift by 32 should be encoded as 0 when permitted |
| 10344 |
if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr)) |
10344 |
if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr)) |
| 10345 |
Amt = 0; |
10345 |
Amt = 0; |
| 10346 |
unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt); |
10346 |
unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt); |
| 10347 |
MCInst TmpInst; |
10347 |
MCInst TmpInst; |
| 10348 |
TmpInst.setOpcode(Opc); |
10348 |
TmpInst.setOpcode(Opc); |
| 10349 |
TmpInst.addOperand(Inst.getOperand(0)); // Rd |
10349 |
TmpInst.addOperand(Inst.getOperand(0)); // Rd |
| 10350 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10350 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10351 |
if (Opc == ARM::MOVsi) |
10351 |
if (Opc == ARM::MOVsi) |
| 10352 |
TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty |
10352 |
TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty |
| 10353 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
10353 |
TmpInst.addOperand(Inst.getOperand(3)); // CondCode |
| 10354 |
TmpInst.addOperand(Inst.getOperand(4)); |
10354 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10355 |
TmpInst.addOperand(Inst.getOperand(5)); // cc_out |
10355 |
TmpInst.addOperand(Inst.getOperand(5)); // cc_out |
| 10356 |
Inst = TmpInst; |
10356 |
Inst = TmpInst; |
| 10357 |
return true; |
10357 |
return true; |
| 10358 |
} |
10358 |
} |
| 10359 |
case ARM::RRXi: { |
10359 |
case ARM::RRXi: { |
| 10360 |
unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0); |
10360 |
unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0); |
| 10361 |
MCInst TmpInst; |
10361 |
MCInst TmpInst; |
| 10362 |
TmpInst.setOpcode(ARM::MOVsi); |
10362 |
TmpInst.setOpcode(ARM::MOVsi); |
| 10363 |
TmpInst.addOperand(Inst.getOperand(0)); // Rd |
10363 |
TmpInst.addOperand(Inst.getOperand(0)); // Rd |
| 10364 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10364 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10365 |
TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty |
10365 |
TmpInst.addOperand(MCOperand::createImm(Shifter)); // Shift value and ty |
| 10366 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
10366 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
| 10367 |
TmpInst.addOperand(Inst.getOperand(3)); |
10367 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10368 |
TmpInst.addOperand(Inst.getOperand(4)); // cc_out |
10368 |
TmpInst.addOperand(Inst.getOperand(4)); // cc_out |
| 10369 |
Inst = TmpInst; |
10369 |
Inst = TmpInst; |
| 10370 |
return true; |
10370 |
return true; |
| 10371 |
} |
10371 |
} |
| 10372 |
case ARM::t2LDMIA_UPD: { |
10372 |
case ARM::t2LDMIA_UPD: { |
| 10373 |
// If this is a load of a single register, then we should use |
10373 |
// If this is a load of a single register, then we should use |
| 10374 |
// a post-indexed LDR instruction instead, per the ARM ARM. |
10374 |
// a post-indexed LDR instruction instead, per the ARM ARM. |
| 10375 |
if (Inst.getNumOperands() != 5) |
10375 |
if (Inst.getNumOperands() != 5) |
| 10376 |
return false; |
10376 |
return false; |
| 10377 |
MCInst TmpInst; |
10377 |
MCInst TmpInst; |
| 10378 |
TmpInst.setOpcode(ARM::t2LDR_POST); |
10378 |
TmpInst.setOpcode(ARM::t2LDR_POST); |
| 10379 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt |
10379 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt |
| 10380 |
TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb |
10380 |
TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb |
| 10381 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10381 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10382 |
TmpInst.addOperand(MCOperand::createImm(4)); |
10382 |
TmpInst.addOperand(MCOperand::createImm(4)); |
| 10383 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
10383 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
| 10384 |
TmpInst.addOperand(Inst.getOperand(3)); |
10384 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10385 |
Inst = TmpInst; |
10385 |
Inst = TmpInst; |
| 10386 |
return true; |
10386 |
return true; |
| 10387 |
} |
10387 |
} |
| 10388 |
case ARM::t2STMDB_UPD: { |
10388 |
case ARM::t2STMDB_UPD: { |
| 10389 |
// If this is a store of a single register, then we should use |
10389 |
// If this is a store of a single register, then we should use |
| 10390 |
// a pre-indexed STR instruction instead, per the ARM ARM. |
10390 |
// a pre-indexed STR instruction instead, per the ARM ARM. |
| 10391 |
if (Inst.getNumOperands() != 5) |
10391 |
if (Inst.getNumOperands() != 5) |
| 10392 |
return false; |
10392 |
return false; |
| 10393 |
MCInst TmpInst; |
10393 |
MCInst TmpInst; |
| 10394 |
TmpInst.setOpcode(ARM::t2STR_PRE); |
10394 |
TmpInst.setOpcode(ARM::t2STR_PRE); |
| 10395 |
TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb |
10395 |
TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb |
| 10396 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt |
10396 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt |
| 10397 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10397 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10398 |
TmpInst.addOperand(MCOperand::createImm(-4)); |
10398 |
TmpInst.addOperand(MCOperand::createImm(-4)); |
| 10399 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
10399 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
| 10400 |
TmpInst.addOperand(Inst.getOperand(3)); |
10400 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10401 |
Inst = TmpInst; |
10401 |
Inst = TmpInst; |
| 10402 |
return true; |
10402 |
return true; |
| 10403 |
} |
10403 |
} |
| 10404 |
case ARM::LDMIA_UPD: |
10404 |
case ARM::LDMIA_UPD: |
| 10405 |
// If this is a load of a single register via a 'pop', then we should use |
10405 |
// If this is a load of a single register via a 'pop', then we should use |
| 10406 |
// a post-indexed LDR instruction instead, per the ARM ARM. |
10406 |
// a post-indexed LDR instruction instead, per the ARM ARM. |
| 10407 |
if (static_cast(*Operands[0]).getToken() == "pop" && |
10407 |
if (static_cast(*Operands[0]).getToken() == "pop" && |
| 10408 |
Inst.getNumOperands() == 5) { |
10408 |
Inst.getNumOperands() == 5) { |
| 10409 |
MCInst TmpInst; |
10409 |
MCInst TmpInst; |
| 10410 |
TmpInst.setOpcode(ARM::LDR_POST_IMM); |
10410 |
TmpInst.setOpcode(ARM::LDR_POST_IMM); |
| 10411 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt |
10411 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt |
| 10412 |
TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb |
10412 |
TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb |
| 10413 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
10413 |
TmpInst.addOperand(Inst.getOperand(1)); // Rn |
| 10414 |
TmpInst.addOperand(MCOperand::createReg(0)); // am2offset |
10414 |
TmpInst.addOperand(MCOperand::createReg(0)); // am2offset |
| 10415 |
TmpInst.addOperand(MCOperand::createImm(4)); |
10415 |
TmpInst.addOperand(MCOperand::createImm(4)); |
| 10416 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
10416 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
| 10417 |
TmpInst.addOperand(Inst.getOperand(3)); |
10417 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10418 |
Inst = TmpInst; |
10418 |
Inst = TmpInst; |
| 10419 |
return true; |
10419 |
return true; |
| 10420 |
} |
10420 |
} |
| 10421 |
break; |
10421 |
break; |
| 10422 |
case ARM::STMDB_UPD: |
10422 |
case ARM::STMDB_UPD: |
| 10423 |
// If this is a store of a single register via a 'push', then we should use |
10423 |
// If this is a store of a single register via a 'push', then we should use |
| 10424 |
// a pre-indexed STR instruction instead, per the ARM ARM. |
10424 |
// a pre-indexed STR instruction instead, per the ARM ARM. |
| 10425 |
if (static_cast(*Operands[0]).getToken() == "push" && |
10425 |
if (static_cast(*Operands[0]).getToken() == "push" && |
| 10426 |
Inst.getNumOperands() == 5) { |
10426 |
Inst.getNumOperands() == 5) { |
| 10427 |
MCInst TmpInst; |
10427 |
MCInst TmpInst; |
| 10428 |
TmpInst.setOpcode(ARM::STR_PRE_IMM); |
10428 |
TmpInst.setOpcode(ARM::STR_PRE_IMM); |
| 10429 |
TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb |
10429 |
TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb |
| 10430 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt |
10430 |
TmpInst.addOperand(Inst.getOperand(4)); // Rt |
| 10431 |
TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12 |
10431 |
TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12 |
| 10432 |
TmpInst.addOperand(MCOperand::createImm(-4)); |
10432 |
TmpInst.addOperand(MCOperand::createImm(-4)); |
| 10433 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
10433 |
TmpInst.addOperand(Inst.getOperand(2)); // CondCode |
| 10434 |
TmpInst.addOperand(Inst.getOperand(3)); |
10434 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10435 |
Inst = TmpInst; |
10435 |
Inst = TmpInst; |
| 10436 |
} |
10436 |
} |
| 10437 |
break; |
10437 |
break; |
| 10438 |
case ARM::t2ADDri12: |
10438 |
case ARM::t2ADDri12: |
| 10439 |
case ARM::t2SUBri12: |
10439 |
case ARM::t2SUBri12: |
| 10440 |
case ARM::t2ADDspImm12: |
10440 |
case ARM::t2ADDspImm12: |
| 10441 |
case ARM::t2SUBspImm12: { |
10441 |
case ARM::t2SUBspImm12: { |
| 10442 |
// If the immediate fits for encoding T3 and the generic |
10442 |
// If the immediate fits for encoding T3 and the generic |
| 10443 |
// mnemonic was used, encoding T3 is preferred. |
10443 |
// mnemonic was used, encoding T3 is preferred. |
| 10444 |
const StringRef Token = static_cast(*Operands[0]).getToken(); |
10444 |
const StringRef Token = static_cast(*Operands[0]).getToken(); |
| 10445 |
if ((Token != "add" && Token != "sub") || |
10445 |
if ((Token != "add" && Token != "sub") || |
| 10446 |
ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1) |
10446 |
ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1) |
| 10447 |
break; |
10447 |
break; |
| 10448 |
switch (Inst.getOpcode()) { |
10448 |
switch (Inst.getOpcode()) { |
| 10449 |
case ARM::t2ADDri12: |
10449 |
case ARM::t2ADDri12: |
| 10450 |
Inst.setOpcode(ARM::t2ADDri); |
10450 |
Inst.setOpcode(ARM::t2ADDri); |
| 10451 |
break; |
10451 |
break; |
| 10452 |
case ARM::t2SUBri12: |
10452 |
case ARM::t2SUBri12: |
| 10453 |
Inst.setOpcode(ARM::t2SUBri); |
10453 |
Inst.setOpcode(ARM::t2SUBri); |
| 10454 |
break; |
10454 |
break; |
| 10455 |
case ARM::t2ADDspImm12: |
10455 |
case ARM::t2ADDspImm12: |
| 10456 |
Inst.setOpcode(ARM::t2ADDspImm); |
10456 |
Inst.setOpcode(ARM::t2ADDspImm); |
| 10457 |
break; |
10457 |
break; |
| 10458 |
case ARM::t2SUBspImm12: |
10458 |
case ARM::t2SUBspImm12: |
| 10459 |
Inst.setOpcode(ARM::t2SUBspImm); |
10459 |
Inst.setOpcode(ARM::t2SUBspImm); |
| 10460 |
break; |
10460 |
break; |
| 10461 |
} |
10461 |
} |
| 10462 |
|
10462 |
|
| 10463 |
Inst.addOperand(MCOperand::createReg(0)); // cc_out |
10463 |
Inst.addOperand(MCOperand::createReg(0)); // cc_out |
| 10464 |
return true; |
10464 |
return true; |
| 10465 |
} |
10465 |
} |
| 10466 |
case ARM::tADDi8: |
10466 |
case ARM::tADDi8: |
| 10467 |
// If the immediate is in the range 0-7, we want tADDi3 iff Rd was |
10467 |
// If the immediate is in the range 0-7, we want tADDi3 iff Rd was |
| 10468 |
// explicitly specified. From the ARM ARM: "Encoding T1 is preferred |
10468 |
// explicitly specified. From the ARM ARM: "Encoding T1 is preferred |
| 10469 |
// to encoding T2 if is specified and encoding T2 is preferred |
10469 |
// to encoding T2 if is specified and encoding T2 is preferred |
| 10470 |
// to encoding T1 if is omitted." |
10470 |
// to encoding T1 if is omitted." |
| 10471 |
if (Inst.getOperand(3).isImm() && |
10471 |
if (Inst.getOperand(3).isImm() && |
| 10472 |
(unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { |
10472 |
(unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { |
| 10473 |
Inst.setOpcode(ARM::tADDi3); |
10473 |
Inst.setOpcode(ARM::tADDi3); |
| 10474 |
return true; |
10474 |
return true; |
| 10475 |
} |
10475 |
} |
| 10476 |
break; |
10476 |
break; |
| 10477 |
case ARM::tSUBi8: |
10477 |
case ARM::tSUBi8: |
| 10478 |
// If the immediate is in the range 0-7, we want tADDi3 iff Rd was |
10478 |
// If the immediate is in the range 0-7, we want tADDi3 iff Rd was |
| 10479 |
// explicitly specified. From the ARM ARM: "Encoding T1 is preferred |
10479 |
// explicitly specified. From the ARM ARM: "Encoding T1 is preferred |
| 10480 |
// to encoding T2 if is specified and encoding T2 is preferred |
10480 |
// to encoding T2 if is specified and encoding T2 is preferred |
| 10481 |
// to encoding T1 if is omitted." |
10481 |
// to encoding T1 if is omitted." |
| 10482 |
if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { |
10482 |
if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { |
| 10483 |
Inst.setOpcode(ARM::tSUBi3); |
10483 |
Inst.setOpcode(ARM::tSUBi3); |
| 10484 |
return true; |
10484 |
return true; |
| 10485 |
} |
10485 |
} |
| 10486 |
break; |
10486 |
break; |
| 10487 |
case ARM::t2ADDri: |
10487 |
case ARM::t2ADDri: |
| 10488 |
case ARM::t2SUBri: { |
10488 |
case ARM::t2SUBri: { |
| 10489 |
// If the destination and first source operand are the same, and |
10489 |
// If the destination and first source operand are the same, and |
| 10490 |
// the flags are compatible with the current IT status, use encoding T2 |
10490 |
// the flags are compatible with the current IT status, use encoding T2 |
| 10491 |
// instead of T3. For compatibility with the system 'as'. Make sure the |
10491 |
// instead of T3. For compatibility with the system 'as'. Make sure the |
| 10492 |
// wide encoding wasn't explicit. |
10492 |
// wide encoding wasn't explicit. |
| 10493 |
if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() || |
10493 |
if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() || |
| 10494 |
!isARMLowRegister(Inst.getOperand(0).getReg()) || |
10494 |
!isARMLowRegister(Inst.getOperand(0).getReg()) || |
| 10495 |
(Inst.getOperand(2).isImm() && |
10495 |
(Inst.getOperand(2).isImm() && |
| 10496 |
(unsigned)Inst.getOperand(2).getImm() > 255) || |
10496 |
(unsigned)Inst.getOperand(2).getImm() > 255) || |
| 10497 |
Inst.getOperand(5).getReg() != (inITBlock() ? 0 : ARM::CPSR) || |
10497 |
Inst.getOperand(5).getReg() != (inITBlock() ? 0 : ARM::CPSR) || |
| 10498 |
HasWideQualifier) |
10498 |
HasWideQualifier) |
| 10499 |
break; |
10499 |
break; |
| 10500 |
MCInst TmpInst; |
10500 |
MCInst TmpInst; |
| 10501 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ? |
10501 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ? |
| 10502 |
ARM::tADDi8 : ARM::tSUBi8); |
10502 |
ARM::tADDi8 : ARM::tSUBi8); |
| 10503 |
TmpInst.addOperand(Inst.getOperand(0)); |
10503 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10504 |
TmpInst.addOperand(Inst.getOperand(5)); |
10504 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 10505 |
TmpInst.addOperand(Inst.getOperand(0)); |
10505 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10506 |
TmpInst.addOperand(Inst.getOperand(2)); |
10506 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 10507 |
TmpInst.addOperand(Inst.getOperand(3)); |
10507 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10508 |
TmpInst.addOperand(Inst.getOperand(4)); |
10508 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10509 |
Inst = TmpInst; |
10509 |
Inst = TmpInst; |
| 10510 |
return true; |
10510 |
return true; |
| 10511 |
} |
10511 |
} |
| 10512 |
case ARM::t2ADDspImm: |
10512 |
case ARM::t2ADDspImm: |
| 10513 |
case ARM::t2SUBspImm: { |
10513 |
case ARM::t2SUBspImm: { |
| 10514 |
// Prefer T1 encoding if possible |
10514 |
// Prefer T1 encoding if possible |
| 10515 |
if (Inst.getOperand(5).getReg() != 0 || HasWideQualifier) |
10515 |
if (Inst.getOperand(5).getReg() != 0 || HasWideQualifier) |
| 10516 |
break; |
10516 |
break; |
| 10517 |
unsigned V = Inst.getOperand(2).getImm(); |
10517 |
unsigned V = Inst.getOperand(2).getImm(); |
| 10518 |
if (V & 3 || V > ((1 << 7) - 1) << 2) |
10518 |
if (V & 3 || V > ((1 << 7) - 1) << 2) |
| 10519 |
break; |
10519 |
break; |
| 10520 |
MCInst TmpInst; |
10520 |
MCInst TmpInst; |
| 10521 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDspImm ? ARM::tADDspi |
10521 |
TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDspImm ? ARM::tADDspi |
| 10522 |
: ARM::tSUBspi); |
10522 |
: ARM::tSUBspi); |
| 10523 |
TmpInst.addOperand(MCOperand::createReg(ARM::SP)); // destination reg |
10523 |
TmpInst.addOperand(MCOperand::createReg(ARM::SP)); // destination reg |
| 10524 |
TmpInst.addOperand(MCOperand::createReg(ARM::SP)); // source reg |
10524 |
TmpInst.addOperand(MCOperand::createReg(ARM::SP)); // source reg |
| 10525 |
TmpInst.addOperand(MCOperand::createImm(V / 4)); // immediate |
10525 |
TmpInst.addOperand(MCOperand::createImm(V / 4)); // immediate |
| 10526 |
TmpInst.addOperand(Inst.getOperand(3)); // pred |
10526 |
TmpInst.addOperand(Inst.getOperand(3)); // pred |
| 10527 |
TmpInst.addOperand(Inst.getOperand(4)); |
10527 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10528 |
Inst = TmpInst; |
10528 |
Inst = TmpInst; |
| 10529 |
return true; |
10529 |
return true; |
| 10530 |
} |
10530 |
} |
| 10531 |
case ARM::t2ADDrr: { |
10531 |
case ARM::t2ADDrr: { |
| 10532 |
// If the destination and first source operand are the same, and |
10532 |
// If the destination and first source operand are the same, and |
| 10533 |
// there's no setting of the flags, use encoding T2 instead of T3. |
10533 |
// there's no setting of the flags, use encoding T2 instead of T3. |
| 10534 |
// Note that this is only for ADD, not SUB. This mirrors the system |
10534 |
// Note that this is only for ADD, not SUB. This mirrors the system |
| 10535 |
// 'as' behaviour. Also take advantage of ADD being commutative. |
10535 |
// 'as' behaviour. Also take advantage of ADD being commutative. |
| 10536 |
// Make sure the wide encoding wasn't explicit. |
10536 |
// Make sure the wide encoding wasn't explicit. |
| 10537 |
bool Swap = false; |
10537 |
bool Swap = false; |
| 10538 |
auto DestReg = Inst.getOperand(0).getReg(); |
10538 |
auto DestReg = Inst.getOperand(0).getReg(); |
| 10539 |
bool Transform = DestReg == Inst.getOperand(1).getReg(); |
10539 |
bool Transform = DestReg == Inst.getOperand(1).getReg(); |
| 10540 |
if (!Transform && DestReg == Inst.getOperand(2).getReg()) { |
10540 |
if (!Transform && DestReg == Inst.getOperand(2).getReg()) { |
| 10541 |
Transform = true; |
10541 |
Transform = true; |
| 10542 |
Swap = true; |
10542 |
Swap = true; |
| 10543 |
} |
10543 |
} |
| 10544 |
if (!Transform || |
10544 |
if (!Transform || |
| 10545 |
Inst.getOperand(5).getReg() != 0 || |
10545 |
Inst.getOperand(5).getReg() != 0 || |
| 10546 |
HasWideQualifier) |
10546 |
HasWideQualifier) |
| 10547 |
break; |
10547 |
break; |
| 10548 |
MCInst TmpInst; |
10548 |
MCInst TmpInst; |
| 10549 |
TmpInst.setOpcode(ARM::tADDhirr); |
10549 |
TmpInst.setOpcode(ARM::tADDhirr); |
| 10550 |
TmpInst.addOperand(Inst.getOperand(0)); |
10550 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10551 |
TmpInst.addOperand(Inst.getOperand(0)); |
10551 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10552 |
TmpInst.addOperand(Inst.getOperand(Swap ? 1 : 2)); |
10552 |
TmpInst.addOperand(Inst.getOperand(Swap ? 1 : 2)); |
| 10553 |
TmpInst.addOperand(Inst.getOperand(3)); |
10553 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10554 |
TmpInst.addOperand(Inst.getOperand(4)); |
10554 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10555 |
Inst = TmpInst; |
10555 |
Inst = TmpInst; |
| 10556 |
return true; |
10556 |
return true; |
| 10557 |
} |
10557 |
} |
| 10558 |
case ARM::tADDrSP: |
10558 |
case ARM::tADDrSP: |
| 10559 |
// If the non-SP source operand and the destination operand are not the |
10559 |
// If the non-SP source operand and the destination operand are not the |
| 10560 |
// same, we need to use the 32-bit encoding if it's available. |
10560 |
// same, we need to use the 32-bit encoding if it's available. |
| 10561 |
if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { |
10561 |
if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { |
| 10562 |
Inst.setOpcode(ARM::t2ADDrr); |
10562 |
Inst.setOpcode(ARM::t2ADDrr); |
| 10563 |
Inst.addOperand(MCOperand::createReg(0)); // cc_out |
10563 |
Inst.addOperand(MCOperand::createReg(0)); // cc_out |
| 10564 |
return true; |
10564 |
return true; |
| 10565 |
} |
10565 |
} |
| 10566 |
break; |
10566 |
break; |
| 10567 |
case ARM::tB: |
10567 |
case ARM::tB: |
| 10568 |
// A Thumb conditional branch outside of an IT block is a tBcc. |
10568 |
// A Thumb conditional branch outside of an IT block is a tBcc. |
| 10569 |
if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) { |
10569 |
if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) { |
| 10570 |
Inst.setOpcode(ARM::tBcc); |
10570 |
Inst.setOpcode(ARM::tBcc); |
| 10571 |
return true; |
10571 |
return true; |
| 10572 |
} |
10572 |
} |
| 10573 |
break; |
10573 |
break; |
| 10574 |
case ARM::t2B: |
10574 |
case ARM::t2B: |
| 10575 |
// A Thumb2 conditional branch outside of an IT block is a t2Bcc. |
10575 |
// A Thumb2 conditional branch outside of an IT block is a t2Bcc. |
| 10576 |
if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){ |
10576 |
if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){ |
| 10577 |
Inst.setOpcode(ARM::t2Bcc); |
10577 |
Inst.setOpcode(ARM::t2Bcc); |
| 10578 |
return true; |
10578 |
return true; |
| 10579 |
} |
10579 |
} |
| 10580 |
break; |
10580 |
break; |
| 10581 |
case ARM::t2Bcc: |
10581 |
case ARM::t2Bcc: |
| 10582 |
// If the conditional is AL or we're in an IT block, we really want t2B. |
10582 |
// If the conditional is AL or we're in an IT block, we really want t2B. |
| 10583 |
if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) { |
10583 |
if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) { |
| 10584 |
Inst.setOpcode(ARM::t2B); |
10584 |
Inst.setOpcode(ARM::t2B); |
| 10585 |
return true; |
10585 |
return true; |
| 10586 |
} |
10586 |
} |
| 10587 |
break; |
10587 |
break; |
| 10588 |
case ARM::tBcc: |
10588 |
case ARM::tBcc: |
| 10589 |
// If the conditional is AL, we really want tB. |
10589 |
// If the conditional is AL, we really want tB. |
| 10590 |
if (Inst.getOperand(1).getImm() == ARMCC::AL) { |
10590 |
if (Inst.getOperand(1).getImm() == ARMCC::AL) { |
| 10591 |
Inst.setOpcode(ARM::tB); |
10591 |
Inst.setOpcode(ARM::tB); |
| 10592 |
return true; |
10592 |
return true; |
| 10593 |
} |
10593 |
} |
| 10594 |
break; |
10594 |
break; |
| 10595 |
case ARM::tLDMIA: { |
10595 |
case ARM::tLDMIA: { |
| 10596 |
// If the register list contains any high registers, or if the writeback |
10596 |
// If the register list contains any high registers, or if the writeback |
| 10597 |
// doesn't match what tLDMIA can do, we need to use the 32-bit encoding |
10597 |
// doesn't match what tLDMIA can do, we need to use the 32-bit encoding |
| 10598 |
// instead if we're in Thumb2. Otherwise, this should have generated |
10598 |
// instead if we're in Thumb2. Otherwise, this should have generated |
| 10599 |
// an error in validateInstruction(). |
10599 |
// an error in validateInstruction(). |
| 10600 |
unsigned Rn = Inst.getOperand(0).getReg(); |
10600 |
unsigned Rn = Inst.getOperand(0).getReg(); |
| 10601 |
bool hasWritebackToken = |
10601 |
bool hasWritebackToken = |
| 10602 |
(static_cast(*Operands[3]).isToken() && |
10602 |
(static_cast(*Operands[3]).isToken() && |
| 10603 |
static_cast(*Operands[3]).getToken() == "!"); |
10603 |
static_cast(*Operands[3]).getToken() == "!"); |
| 10604 |
bool listContainsBase; |
10604 |
bool listContainsBase; |
| 10605 |
if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) || |
10605 |
if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) || |
| 10606 |
(!listContainsBase && !hasWritebackToken) || |
10606 |
(!listContainsBase && !hasWritebackToken) || |
| 10607 |
(listContainsBase && hasWritebackToken)) { |
10607 |
(listContainsBase && hasWritebackToken)) { |
| 10608 |
// 16-bit encoding isn't sufficient. Switch to the 32-bit version. |
10608 |
// 16-bit encoding isn't sufficient. Switch to the 32-bit version. |
| 10609 |
assert(isThumbTwo()); |
10609 |
assert(isThumbTwo()); |
| 10610 |
Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA); |
10610 |
Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA); |
| 10611 |
// If we're switching to the updating version, we need to insert |
10611 |
// If we're switching to the updating version, we need to insert |
| 10612 |
// the writeback tied operand. |
10612 |
// the writeback tied operand. |
| 10613 |
if (hasWritebackToken) |
10613 |
if (hasWritebackToken) |
| 10614 |
Inst.insert(Inst.begin(), |
10614 |
Inst.insert(Inst.begin(), |
| 10615 |
MCOperand::createReg(Inst.getOperand(0).getReg())); |
10615 |
MCOperand::createReg(Inst.getOperand(0).getReg())); |
| 10616 |
return true; |
10616 |
return true; |
| 10617 |
} |
10617 |
} |
| 10618 |
break; |
10618 |
break; |
| 10619 |
} |
10619 |
} |
| 10620 |
case ARM::tSTMIA_UPD: { |
10620 |
case ARM::tSTMIA_UPD: { |
| 10621 |
// If the register list contains any high registers, we need to use |
10621 |
// If the register list contains any high registers, we need to use |
| 10622 |
// the 32-bit encoding instead if we're in Thumb2. Otherwise, this |
10622 |
// the 32-bit encoding instead if we're in Thumb2. Otherwise, this |
| 10623 |
// should have generated an error in validateInstruction(). |
10623 |
// should have generated an error in validateInstruction(). |
| 10624 |
unsigned Rn = Inst.getOperand(0).getReg(); |
10624 |
unsigned Rn = Inst.getOperand(0).getReg(); |
| 10625 |
bool listContainsBase; |
10625 |
bool listContainsBase; |
| 10626 |
if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) { |
10626 |
if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) { |
| 10627 |
// 16-bit encoding isn't sufficient. Switch to the 32-bit version. |
10627 |
// 16-bit encoding isn't sufficient. Switch to the 32-bit version. |
| 10628 |
assert(isThumbTwo()); |
10628 |
assert(isThumbTwo()); |
| 10629 |
Inst.setOpcode(ARM::t2STMIA_UPD); |
10629 |
Inst.setOpcode(ARM::t2STMIA_UPD); |
| 10630 |
return true; |
10630 |
return true; |
| 10631 |
} |
10631 |
} |
| 10632 |
break; |
10632 |
break; |
| 10633 |
} |
10633 |
} |
| 10634 |
case ARM::tPOP: { |
10634 |
case ARM::tPOP: { |
| 10635 |
bool listContainsBase; |
10635 |
bool listContainsBase; |
| 10636 |
// If the register list contains any high registers, we need to use |
10636 |
// If the register list contains any high registers, we need to use |
| 10637 |
// the 32-bit encoding instead if we're in Thumb2. Otherwise, this |
10637 |
// the 32-bit encoding instead if we're in Thumb2. Otherwise, this |
| 10638 |
// should have generated an error in validateInstruction(). |
10638 |
// should have generated an error in validateInstruction(). |
| 10639 |
if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase)) |
10639 |
if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase)) |
| 10640 |
return false; |
10640 |
return false; |
| 10641 |
assert(isThumbTwo()); |
10641 |
assert(isThumbTwo()); |
| 10642 |
Inst.setOpcode(ARM::t2LDMIA_UPD); |
10642 |
Inst.setOpcode(ARM::t2LDMIA_UPD); |
| 10643 |
// Add the base register and writeback operands. |
10643 |
// Add the base register and writeback operands. |
| 10644 |
Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); |
10644 |
Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); |
| 10645 |
Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); |
10645 |
Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); |
| 10646 |
return true; |
10646 |
return true; |
| 10647 |
} |
10647 |
} |
| 10648 |
case ARM::tPUSH: { |
10648 |
case ARM::tPUSH: { |
| 10649 |
bool listContainsBase; |
10649 |
bool listContainsBase; |
| 10650 |
if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase)) |
10650 |
if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase)) |
| 10651 |
return false; |
10651 |
return false; |
| 10652 |
assert(isThumbTwo()); |
10652 |
assert(isThumbTwo()); |
| 10653 |
Inst.setOpcode(ARM::t2STMDB_UPD); |
10653 |
Inst.setOpcode(ARM::t2STMDB_UPD); |
| 10654 |
// Add the base register and writeback operands. |
10654 |
// Add the base register and writeback operands. |
| 10655 |
Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); |
10655 |
Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); |
| 10656 |
Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); |
10656 |
Inst.insert(Inst.begin(), MCOperand::createReg(ARM::SP)); |
| 10657 |
return true; |
10657 |
return true; |
| 10658 |
} |
10658 |
} |
| 10659 |
case ARM::t2MOVi: |
10659 |
case ARM::t2MOVi: |
| 10660 |
// If we can use the 16-bit encoding and the user didn't explicitly |
10660 |
// If we can use the 16-bit encoding and the user didn't explicitly |
| 10661 |
// request the 32-bit variant, transform it here. |
10661 |
// request the 32-bit variant, transform it here. |
| 10662 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
10662 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
| 10663 |
(Inst.getOperand(1).isImm() && |
10663 |
(Inst.getOperand(1).isImm() && |
| 10664 |
(unsigned)Inst.getOperand(1).getImm() <= 255) && |
10664 |
(unsigned)Inst.getOperand(1).getImm() <= 255) && |
| 10665 |
Inst.getOperand(4).getReg() == (inITBlock() ? 0 : ARM::CPSR) && |
10665 |
Inst.getOperand(4).getReg() == (inITBlock() ? 0 : ARM::CPSR) && |
| 10666 |
!HasWideQualifier) { |
10666 |
!HasWideQualifier) { |
| 10667 |
// The operands aren't in the same order for tMOVi8... |
10667 |
// The operands aren't in the same order for tMOVi8... |
| 10668 |
MCInst TmpInst; |
10668 |
MCInst TmpInst; |
| 10669 |
TmpInst.setOpcode(ARM::tMOVi8); |
10669 |
TmpInst.setOpcode(ARM::tMOVi8); |
| 10670 |
TmpInst.addOperand(Inst.getOperand(0)); |
10670 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10671 |
TmpInst.addOperand(Inst.getOperand(4)); |
10671 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10672 |
TmpInst.addOperand(Inst.getOperand(1)); |
10672 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 10673 |
TmpInst.addOperand(Inst.getOperand(2)); |
10673 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 10674 |
TmpInst.addOperand(Inst.getOperand(3)); |
10674 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10675 |
Inst = TmpInst; |
10675 |
Inst = TmpInst; |
| 10676 |
return true; |
10676 |
return true; |
| 10677 |
} |
10677 |
} |
| 10678 |
break; |
10678 |
break; |
| 10679 |
|
10679 |
|
| 10680 |
case ARM::t2MOVr: |
10680 |
case ARM::t2MOVr: |
| 10681 |
// If we can use the 16-bit encoding and the user didn't explicitly |
10681 |
// If we can use the 16-bit encoding and the user didn't explicitly |
| 10682 |
// request the 32-bit variant, transform it here. |
10682 |
// request the 32-bit variant, transform it here. |
| 10683 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
10683 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
| 10684 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
10684 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
| 10685 |
Inst.getOperand(2).getImm() == ARMCC::AL && |
10685 |
Inst.getOperand(2).getImm() == ARMCC::AL && |
| 10686 |
Inst.getOperand(4).getReg() == ARM::CPSR && |
10686 |
Inst.getOperand(4).getReg() == ARM::CPSR && |
| 10687 |
!HasWideQualifier) { |
10687 |
!HasWideQualifier) { |
| 10688 |
// The operands aren't the same for tMOV[S]r... (no cc_out) |
10688 |
// The operands aren't the same for tMOV[S]r... (no cc_out) |
| 10689 |
MCInst TmpInst; |
10689 |
MCInst TmpInst; |
| 10690 |
unsigned Op = Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr; |
10690 |
unsigned Op = Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr; |
| 10691 |
TmpInst.setOpcode(Op); |
10691 |
TmpInst.setOpcode(Op); |
| 10692 |
TmpInst.addOperand(Inst.getOperand(0)); |
10692 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10693 |
TmpInst.addOperand(Inst.getOperand(1)); |
10693 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 10694 |
if (Op == ARM::tMOVr) { |
10694 |
if (Op == ARM::tMOVr) { |
| 10695 |
TmpInst.addOperand(Inst.getOperand(2)); |
10695 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 10696 |
TmpInst.addOperand(Inst.getOperand(3)); |
10696 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10697 |
} |
10697 |
} |
| 10698 |
Inst = TmpInst; |
10698 |
Inst = TmpInst; |
| 10699 |
return true; |
10699 |
return true; |
| 10700 |
} |
10700 |
} |
| 10701 |
break; |
10701 |
break; |
| 10702 |
|
10702 |
|
| 10703 |
case ARM::t2SXTH: |
10703 |
case ARM::t2SXTH: |
| 10704 |
case ARM::t2SXTB: |
10704 |
case ARM::t2SXTB: |
| 10705 |
case ARM::t2UXTH: |
10705 |
case ARM::t2UXTH: |
| 10706 |
case ARM::t2UXTB: |
10706 |
case ARM::t2UXTB: |
| 10707 |
// If we can use the 16-bit encoding and the user didn't explicitly |
10707 |
// If we can use the 16-bit encoding and the user didn't explicitly |
| 10708 |
// request the 32-bit variant, transform it here. |
10708 |
// request the 32-bit variant, transform it here. |
| 10709 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
10709 |
if (isARMLowRegister(Inst.getOperand(0).getReg()) && |
| 10710 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
10710 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
| 10711 |
Inst.getOperand(2).getImm() == 0 && |
10711 |
Inst.getOperand(2).getImm() == 0 && |
| 10712 |
!HasWideQualifier) { |
10712 |
!HasWideQualifier) { |
| 10713 |
unsigned NewOpc; |
10713 |
unsigned NewOpc; |
| 10714 |
switch (Inst.getOpcode()) { |
10714 |
switch (Inst.getOpcode()) { |
| 10715 |
default: llvm_unreachable("Illegal opcode!"); |
10715 |
default: llvm_unreachable("Illegal opcode!"); |
| 10716 |
case ARM::t2SXTH: NewOpc = ARM::tSXTH; break; |
10716 |
case ARM::t2SXTH: NewOpc = ARM::tSXTH; break; |
| 10717 |
case ARM::t2SXTB: NewOpc = ARM::tSXTB; break; |
10717 |
case ARM::t2SXTB: NewOpc = ARM::tSXTB; break; |
| 10718 |
case ARM::t2UXTH: NewOpc = ARM::tUXTH; break; |
10718 |
case ARM::t2UXTH: NewOpc = ARM::tUXTH; break; |
| 10719 |
case ARM::t2UXTB: NewOpc = ARM::tUXTB; break; |
10719 |
case ARM::t2UXTB: NewOpc = ARM::tUXTB; break; |
| 10720 |
} |
10720 |
} |
| 10721 |
// The operands aren't the same for thumb1 (no rotate operand). |
10721 |
// The operands aren't the same for thumb1 (no rotate operand). |
| 10722 |
MCInst TmpInst; |
10722 |
MCInst TmpInst; |
| 10723 |
TmpInst.setOpcode(NewOpc); |
10723 |
TmpInst.setOpcode(NewOpc); |
| 10724 |
TmpInst.addOperand(Inst.getOperand(0)); |
10724 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10725 |
TmpInst.addOperand(Inst.getOperand(1)); |
10725 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 10726 |
TmpInst.addOperand(Inst.getOperand(3)); |
10726 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10727 |
TmpInst.addOperand(Inst.getOperand(4)); |
10727 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10728 |
Inst = TmpInst; |
10728 |
Inst = TmpInst; |
| 10729 |
return true; |
10729 |
return true; |
| 10730 |
} |
10730 |
} |
| 10731 |
break; |
10731 |
break; |
| 10732 |
|
10732 |
|
| 10733 |
case ARM::MOVsi: { |
10733 |
case ARM::MOVsi: { |
| 10734 |
ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm()); |
10734 |
ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm()); |
| 10735 |
// rrx shifts and asr/lsr of #32 is encoded as 0 |
10735 |
// rrx shifts and asr/lsr of #32 is encoded as 0 |
| 10736 |
if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr) |
10736 |
if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr) |
| 10737 |
return false; |
10737 |
return false; |
| 10738 |
if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) { |
10738 |
if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) { |
| 10739 |
// Shifting by zero is accepted as a vanilla 'MOVr' |
10739 |
// Shifting by zero is accepted as a vanilla 'MOVr' |
| 10740 |
MCInst TmpInst; |
10740 |
MCInst TmpInst; |
| 10741 |
TmpInst.setOpcode(ARM::MOVr); |
10741 |
TmpInst.setOpcode(ARM::MOVr); |
| 10742 |
TmpInst.addOperand(Inst.getOperand(0)); |
10742 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10743 |
TmpInst.addOperand(Inst.getOperand(1)); |
10743 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 10744 |
TmpInst.addOperand(Inst.getOperand(3)); |
10744 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10745 |
TmpInst.addOperand(Inst.getOperand(4)); |
10745 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10746 |
TmpInst.addOperand(Inst.getOperand(5)); |
10746 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 10747 |
Inst = TmpInst; |
10747 |
Inst = TmpInst; |
| 10748 |
return true; |
10748 |
return true; |
| 10749 |
} |
10749 |
} |
| 10750 |
return false; |
10750 |
return false; |
| 10751 |
} |
10751 |
} |
| 10752 |
case ARM::ANDrsi: |
10752 |
case ARM::ANDrsi: |
| 10753 |
case ARM::ORRrsi: |
10753 |
case ARM::ORRrsi: |
| 10754 |
case ARM::EORrsi: |
10754 |
case ARM::EORrsi: |
| 10755 |
case ARM::BICrsi: |
10755 |
case ARM::BICrsi: |
| 10756 |
case ARM::SUBrsi: |
10756 |
case ARM::SUBrsi: |
| 10757 |
case ARM::ADDrsi: { |
10757 |
case ARM::ADDrsi: { |
| 10758 |
unsigned newOpc; |
10758 |
unsigned newOpc; |
| 10759 |
ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm()); |
10759 |
ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm()); |
| 10760 |
if (SOpc == ARM_AM::rrx) return false; |
10760 |
if (SOpc == ARM_AM::rrx) return false; |
| 10761 |
switch (Inst.getOpcode()) { |
10761 |
switch (Inst.getOpcode()) { |
| 10762 |
default: llvm_unreachable("unexpected opcode!"); |
10762 |
default: llvm_unreachable("unexpected opcode!"); |
| 10763 |
case ARM::ANDrsi: newOpc = ARM::ANDrr; break; |
10763 |
case ARM::ANDrsi: newOpc = ARM::ANDrr; break; |
| 10764 |
case ARM::ORRrsi: newOpc = ARM::ORRrr; break; |
10764 |
case ARM::ORRrsi: newOpc = ARM::ORRrr; break; |
| 10765 |
case ARM::EORrsi: newOpc = ARM::EORrr; break; |
10765 |
case ARM::EORrsi: newOpc = ARM::EORrr; break; |
| 10766 |
case ARM::BICrsi: newOpc = ARM::BICrr; break; |
10766 |
case ARM::BICrsi: newOpc = ARM::BICrr; break; |
| 10767 |
case ARM::SUBrsi: newOpc = ARM::SUBrr; break; |
10767 |
case ARM::SUBrsi: newOpc = ARM::SUBrr; break; |
| 10768 |
case ARM::ADDrsi: newOpc = ARM::ADDrr; break; |
10768 |
case ARM::ADDrsi: newOpc = ARM::ADDrr; break; |
| 10769 |
} |
10769 |
} |
| 10770 |
// If the shift is by zero, use the non-shifted instruction definition. |
10770 |
// If the shift is by zero, use the non-shifted instruction definition. |
| 10771 |
// The exception is for right shifts, where 0 == 32 |
10771 |
// The exception is for right shifts, where 0 == 32 |
| 10772 |
if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0 && |
10772 |
if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0 && |
| 10773 |
!(SOpc == ARM_AM::lsr || SOpc == ARM_AM::asr)) { |
10773 |
!(SOpc == ARM_AM::lsr || SOpc == ARM_AM::asr)) { |
| 10774 |
MCInst TmpInst; |
10774 |
MCInst TmpInst; |
| 10775 |
TmpInst.setOpcode(newOpc); |
10775 |
TmpInst.setOpcode(newOpc); |
| 10776 |
TmpInst.addOperand(Inst.getOperand(0)); |
10776 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10777 |
TmpInst.addOperand(Inst.getOperand(1)); |
10777 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 10778 |
TmpInst.addOperand(Inst.getOperand(2)); |
10778 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 10779 |
TmpInst.addOperand(Inst.getOperand(4)); |
10779 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10780 |
TmpInst.addOperand(Inst.getOperand(5)); |
10780 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 10781 |
TmpInst.addOperand(Inst.getOperand(6)); |
10781 |
TmpInst.addOperand(Inst.getOperand(6)); |
| 10782 |
Inst = TmpInst; |
10782 |
Inst = TmpInst; |
| 10783 |
return true; |
10783 |
return true; |
| 10784 |
} |
10784 |
} |
| 10785 |
return false; |
10785 |
return false; |
| 10786 |
} |
10786 |
} |
| 10787 |
case ARM::ITasm: |
10787 |
case ARM::ITasm: |
| 10788 |
case ARM::t2IT: { |
10788 |
case ARM::t2IT: { |
| 10789 |
// Set up the IT block state according to the IT instruction we just |
10789 |
// Set up the IT block state according to the IT instruction we just |
| 10790 |
// matched. |
10790 |
// matched. |
| 10791 |
assert(!inITBlock() && "nested IT blocks?!"); |
10791 |
assert(!inITBlock() && "nested IT blocks?!"); |
| 10792 |
startExplicitITBlock(ARMCC::CondCodes(Inst.getOperand(0).getImm()), |
10792 |
startExplicitITBlock(ARMCC::CondCodes(Inst.getOperand(0).getImm()), |
| 10793 |
Inst.getOperand(1).getImm()); |
10793 |
Inst.getOperand(1).getImm()); |
| 10794 |
break; |
10794 |
break; |
| 10795 |
} |
10795 |
} |
| 10796 |
case ARM::t2LSLrr: |
10796 |
case ARM::t2LSLrr: |
| 10797 |
case ARM::t2LSRrr: |
10797 |
case ARM::t2LSRrr: |
| 10798 |
case ARM::t2ASRrr: |
10798 |
case ARM::t2ASRrr: |
| 10799 |
case ARM::t2SBCrr: |
10799 |
case ARM::t2SBCrr: |
| 10800 |
case ARM::t2RORrr: |
10800 |
case ARM::t2RORrr: |
| 10801 |
case ARM::t2BICrr: |
10801 |
case ARM::t2BICrr: |
| 10802 |
// Assemblers should use the narrow encodings of these instructions when permissible. |
10802 |
// Assemblers should use the narrow encodings of these instructions when permissible. |
| 10803 |
if ((isARMLowRegister(Inst.getOperand(1).getReg()) && |
10803 |
if ((isARMLowRegister(Inst.getOperand(1).getReg()) && |
| 10804 |
isARMLowRegister(Inst.getOperand(2).getReg())) && |
10804 |
isARMLowRegister(Inst.getOperand(2).getReg())) && |
| 10805 |
Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && |
10805 |
Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() && |
| 10806 |
Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) && |
10806 |
Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) && |
| 10807 |
!HasWideQualifier) { |
10807 |
!HasWideQualifier) { |
| 10808 |
unsigned NewOpc; |
10808 |
unsigned NewOpc; |
| 10809 |
switch (Inst.getOpcode()) { |
10809 |
switch (Inst.getOpcode()) { |
| 10810 |
default: llvm_unreachable("unexpected opcode"); |
10810 |
default: llvm_unreachable("unexpected opcode"); |
| 10811 |
case ARM::t2LSLrr: NewOpc = ARM::tLSLrr; break; |
10811 |
case ARM::t2LSLrr: NewOpc = ARM::tLSLrr; break; |
| 10812 |
case ARM::t2LSRrr: NewOpc = ARM::tLSRrr; break; |
10812 |
case ARM::t2LSRrr: NewOpc = ARM::tLSRrr; break; |
| 10813 |
case ARM::t2ASRrr: NewOpc = ARM::tASRrr; break; |
10813 |
case ARM::t2ASRrr: NewOpc = ARM::tASRrr; break; |
| 10814 |
case ARM::t2SBCrr: NewOpc = ARM::tSBC; break; |
10814 |
case ARM::t2SBCrr: NewOpc = ARM::tSBC; break; |
| 10815 |
case ARM::t2RORrr: NewOpc = ARM::tROR; break; |
10815 |
case ARM::t2RORrr: NewOpc = ARM::tROR; break; |
| 10816 |
case ARM::t2BICrr: NewOpc = ARM::tBIC; break; |
10816 |
case ARM::t2BICrr: NewOpc = ARM::tBIC; break; |
| 10817 |
} |
10817 |
} |
| 10818 |
MCInst TmpInst; |
10818 |
MCInst TmpInst; |
| 10819 |
TmpInst.setOpcode(NewOpc); |
10819 |
TmpInst.setOpcode(NewOpc); |
| 10820 |
TmpInst.addOperand(Inst.getOperand(0)); |
10820 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10821 |
TmpInst.addOperand(Inst.getOperand(5)); |
10821 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 10822 |
TmpInst.addOperand(Inst.getOperand(1)); |
10822 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 10823 |
TmpInst.addOperand(Inst.getOperand(2)); |
10823 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 10824 |
TmpInst.addOperand(Inst.getOperand(3)); |
10824 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10825 |
TmpInst.addOperand(Inst.getOperand(4)); |
10825 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10826 |
Inst = TmpInst; |
10826 |
Inst = TmpInst; |
| 10827 |
return true; |
10827 |
return true; |
| 10828 |
} |
10828 |
} |
| 10829 |
return false; |
10829 |
return false; |
| 10830 |
|
10830 |
|
| 10831 |
case ARM::t2ANDrr: |
10831 |
case ARM::t2ANDrr: |
| 10832 |
case ARM::t2EORrr: |
10832 |
case ARM::t2EORrr: |
| 10833 |
case ARM::t2ADCrr: |
10833 |
case ARM::t2ADCrr: |
| 10834 |
case ARM::t2ORRrr: |
10834 |
case ARM::t2ORRrr: |
| 10835 |
// Assemblers should use the narrow encodings of these instructions when permissible. |
10835 |
// Assemblers should use the narrow encodings of these instructions when permissible. |
| 10836 |
// These instructions are special in that they are commutable, so shorter encodings |
10836 |
// These instructions are special in that they are commutable, so shorter encodings |
| 10837 |
// are available more often. |
10837 |
// are available more often. |
| 10838 |
if ((isARMLowRegister(Inst.getOperand(1).getReg()) && |
10838 |
if ((isARMLowRegister(Inst.getOperand(1).getReg()) && |
| 10839 |
isARMLowRegister(Inst.getOperand(2).getReg())) && |
10839 |
isARMLowRegister(Inst.getOperand(2).getReg())) && |
| 10840 |
(Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() || |
10840 |
(Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() || |
| 10841 |
Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()) && |
10841 |
Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()) && |
| 10842 |
Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) && |
10842 |
Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) && |
| 10843 |
!HasWideQualifier) { |
10843 |
!HasWideQualifier) { |
| 10844 |
unsigned NewOpc; |
10844 |
unsigned NewOpc; |
| 10845 |
switch (Inst.getOpcode()) { |
10845 |
switch (Inst.getOpcode()) { |
| 10846 |
default: llvm_unreachable("unexpected opcode"); |
10846 |
default: llvm_unreachable("unexpected opcode"); |
| 10847 |
case ARM::t2ADCrr: NewOpc = ARM::tADC; break; |
10847 |
case ARM::t2ADCrr: NewOpc = ARM::tADC; break; |
| 10848 |
case ARM::t2ANDrr: NewOpc = ARM::tAND; break; |
10848 |
case ARM::t2ANDrr: NewOpc = ARM::tAND; break; |
| 10849 |
case ARM::t2EORrr: NewOpc = ARM::tEOR; break; |
10849 |
case ARM::t2EORrr: NewOpc = ARM::tEOR; break; |
| 10850 |
case ARM::t2ORRrr: NewOpc = ARM::tORR; break; |
10850 |
case ARM::t2ORRrr: NewOpc = ARM::tORR; break; |
| 10851 |
} |
10851 |
} |
| 10852 |
MCInst TmpInst; |
10852 |
MCInst TmpInst; |
| 10853 |
TmpInst.setOpcode(NewOpc); |
10853 |
TmpInst.setOpcode(NewOpc); |
| 10854 |
TmpInst.addOperand(Inst.getOperand(0)); |
10854 |
TmpInst.addOperand(Inst.getOperand(0)); |
| 10855 |
TmpInst.addOperand(Inst.getOperand(5)); |
10855 |
TmpInst.addOperand(Inst.getOperand(5)); |
| 10856 |
if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) { |
10856 |
if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) { |
| 10857 |
TmpInst.addOperand(Inst.getOperand(1)); |
10857 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 10858 |
TmpInst.addOperand(Inst.getOperand(2)); |
10858 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 10859 |
} else { |
10859 |
} else { |
| 10860 |
TmpInst.addOperand(Inst.getOperand(2)); |
10860 |
TmpInst.addOperand(Inst.getOperand(2)); |
| 10861 |
TmpInst.addOperand(Inst.getOperand(1)); |
10861 |
TmpInst.addOperand(Inst.getOperand(1)); |
| 10862 |
} |
10862 |
} |
| 10863 |
TmpInst.addOperand(Inst.getOperand(3)); |
10863 |
TmpInst.addOperand(Inst.getOperand(3)); |
| 10864 |
TmpInst.addOperand(Inst.getOperand(4)); |
10864 |
TmpInst.addOperand(Inst.getOperand(4)); |
| 10865 |
Inst = TmpInst; |
10865 |
Inst = TmpInst; |
| 10866 |
return true; |
10866 |
return true; |
| 10867 |
} |
10867 |
} |
| 10868 |
return false; |
10868 |
return false; |
| 10869 |
case ARM::MVE_VPST: |
10869 |
case ARM::MVE_VPST: |
| 10870 |
case ARM::MVE_VPTv16i8: |
10870 |
case ARM::MVE_VPTv16i8: |
| 10871 |
case ARM::MVE_VPTv8i16: |
10871 |
case ARM::MVE_VPTv8i16: |
| 10872 |
case ARM::MVE_VPTv4i32: |
10872 |
case ARM::MVE_VPTv4i32: |
| 10873 |
case ARM::MVE_VPTv16u8: |
10873 |
case ARM::MVE_VPTv16u8: |
| 10874 |
case ARM::MVE_VPTv8u16: |
10874 |
case ARM::MVE_VPTv8u16: |
| 10875 |
case ARM::MVE_VPTv4u32: |
10875 |
case ARM::MVE_VPTv4u32: |
| 10876 |
case ARM::MVE_VPTv16s8: |
10876 |
case ARM::MVE_VPTv16s8: |
| 10877 |
case ARM::MVE_VPTv8s16: |
10877 |
case ARM::MVE_VPTv8s16: |
| 10878 |
case ARM::MVE_VPTv4s32: |
10878 |
case ARM::MVE_VPTv4s32: |
| 10879 |
case ARM::MVE_VPTv4f32: |
10879 |
case ARM::MVE_VPTv4f32: |
| 10880 |
case ARM::MVE_VPTv8f16: |
10880 |
case ARM::MVE_VPTv8f16: |
| 10881 |
case ARM::MVE_VPTv16i8r: |
10881 |
case ARM::MVE_VPTv16i8r: |
| 10882 |
case ARM::MVE_VPTv8i16r: |
10882 |
case ARM::MVE_VPTv8i16r: |
| 10883 |
case ARM::MVE_VPTv4i32r: |
10883 |
case ARM::MVE_VPTv4i32r: |
| 10884 |
case ARM::MVE_VPTv16u8r: |
10884 |
case ARM::MVE_VPTv16u8r: |
| 10885 |
case ARM::MVE_VPTv8u16r: |
10885 |
case ARM::MVE_VPTv8u16r: |
| 10886 |
case ARM::MVE_VPTv4u32r: |
10886 |
case ARM::MVE_VPTv4u32r: |
| 10887 |
case ARM::MVE_VPTv16s8r: |
10887 |
case ARM::MVE_VPTv16s8r: |
| 10888 |
case ARM::MVE_VPTv8s16r: |
10888 |
case ARM::MVE_VPTv8s16r: |
| 10889 |
case ARM::MVE_VPTv4s32r: |
10889 |
case ARM::MVE_VPTv4s32r: |
| 10890 |
case ARM::MVE_VPTv4f32r: |
10890 |
case ARM::MVE_VPTv4f32r: |
| 10891 |
case ARM::MVE_VPTv8f16r: { |
10891 |
case ARM::MVE_VPTv8f16r: { |
| 10892 |
assert(!inVPTBlock() && "Nested VPT blocks are not allowed"); |
10892 |
assert(!inVPTBlock() && "Nested VPT blocks are not allowed"); |
| 10893 |
MCOperand &MO = Inst.getOperand(0); |
10893 |
MCOperand &MO = Inst.getOperand(0); |
| 10894 |
VPTState.Mask = MO.getImm(); |
10894 |
VPTState.Mask = MO.getImm(); |
| 10895 |
VPTState.CurPosition = 0; |
10895 |
VPTState.CurPosition = 0; |
| 10896 |
break; |
10896 |
break; |
| 10897 |
} |
10897 |
} |
| 10898 |
} |
10898 |
} |
| 10899 |
return false; |
10899 |
return false; |
| 10900 |
} |
10900 |
} |
| 10901 |
|
10901 |
|
| 10902 |
unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { |
10902 |
unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { |
| 10903 |
// 16-bit thumb arithmetic instructions either require or preclude the 'S' |
10903 |
// 16-bit thumb arithmetic instructions either require or preclude the 'S' |
| 10904 |
// suffix depending on whether they're in an IT block or not. |
10904 |
// suffix depending on whether they're in an IT block or not. |
| 10905 |
unsigned Opc = Inst.getOpcode(); |
10905 |
unsigned Opc = Inst.getOpcode(); |
| 10906 |
const MCInstrDesc &MCID = MII.get(Opc); |
10906 |
const MCInstrDesc &MCID = MII.get(Opc); |
| 10907 |
if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) { |
10907 |
if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) { |
| 10908 |
assert(MCID.hasOptionalDef() && |
10908 |
assert(MCID.hasOptionalDef() && |
| 10909 |
"optionally flag setting instruction missing optional def operand"); |
10909 |
"optionally flag setting instruction missing optional def operand"); |
| 10910 |
assert(MCID.NumOperands == Inst.getNumOperands() && |
10910 |
assert(MCID.NumOperands == Inst.getNumOperands() && |
| 10911 |
"operand count mismatch!"); |
10911 |
"operand count mismatch!"); |
| 10912 |
// Find the optional-def operand (cc_out). |
10912 |
// Find the optional-def operand (cc_out). |
| 10913 |
unsigned OpNo; |
10913 |
unsigned OpNo; |
| 10914 |
for (OpNo = 0; |
10914 |
for (OpNo = 0; |
| 10915 |
OpNo < MCID.NumOperands && !MCID.operands()[OpNo].isOptionalDef(); |
10915 |
OpNo < MCID.NumOperands && !MCID.operands()[OpNo].isOptionalDef(); |
| 10916 |
++OpNo) |
10916 |
++OpNo) |
| 10917 |
; |
10917 |
; |
| 10918 |
// If we're parsing Thumb1, reject it completely. |
10918 |
// If we're parsing Thumb1, reject it completely. |
| 10919 |
if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR) |
10919 |
if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR) |
| 10920 |
return Match_RequiresFlagSetting; |
10920 |
return Match_RequiresFlagSetting; |
| 10921 |
// If we're parsing Thumb2, which form is legal depends on whether we're |
10921 |
// If we're parsing Thumb2, which form is legal depends on whether we're |
| 10922 |
// in an IT block. |
10922 |
// in an IT block. |
| 10923 |
if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR && |
10923 |
if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR && |
| 10924 |
!inITBlock()) |
10924 |
!inITBlock()) |
| 10925 |
return Match_RequiresITBlock; |
10925 |
return Match_RequiresITBlock; |
| 10926 |
if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR && |
10926 |
if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR && |
| 10927 |
inITBlock()) |
10927 |
inITBlock()) |
| 10928 |
return Match_RequiresNotITBlock; |
10928 |
return Match_RequiresNotITBlock; |
| 10929 |
// LSL with zero immediate is not allowed in an IT block |
10929 |
// LSL with zero immediate is not allowed in an IT block |
| 10930 |
if (Opc == ARM::tLSLri && Inst.getOperand(3).getImm() == 0 && inITBlock()) |
10930 |
if (Opc == ARM::tLSLri && Inst.getOperand(3).getImm() == 0 && inITBlock()) |
| 10931 |
return Match_RequiresNotITBlock; |
10931 |
return Match_RequiresNotITBlock; |
| 10932 |
} else if (isThumbOne()) { |
10932 |
} else if (isThumbOne()) { |
| 10933 |
// Some high-register supporting Thumb1 encodings only allow both registers |
10933 |
// Some high-register supporting Thumb1 encodings only allow both registers |
| 10934 |
// to be from r0-r7 when in Thumb2. |
10934 |
// to be from r0-r7 when in Thumb2. |
| 10935 |
if (Opc == ARM::tADDhirr && !hasV6MOps() && |
10935 |
if (Opc == ARM::tADDhirr && !hasV6MOps() && |
| 10936 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
10936 |
isARMLowRegister(Inst.getOperand(1).getReg()) && |
| 10937 |
isARMLowRegister(Inst.getOperand(2).getReg())) |
10937 |
isARMLowRegister(Inst.getOperand(2).getReg())) |
| 10938 |
return Match_RequiresThumb2; |
10938 |
return Match_RequiresThumb2; |
| 10939 |
// Others only require ARMv6 or later. |
10939 |
// Others only require ARMv6 or later. |
| 10940 |
else if (Opc == ARM::tMOVr && !hasV6Ops() && |
10940 |
else if (Opc == ARM::tMOVr && !hasV6Ops() && |
| 10941 |
isARMLowRegister(Inst.getOperand(0).getReg()) && |
10941 |
isARMLowRegister(Inst.getOperand(0).getReg()) && |
| 10942 |
isARMLowRegister(Inst.getOperand(1).getReg())) |
10942 |
isARMLowRegister(Inst.getOperand(1).getReg())) |
| 10943 |
return Match_RequiresV6; |
10943 |
return Match_RequiresV6; |
| 10944 |
} |
10944 |
} |
| 10945 |
|
10945 |
|
| 10946 |
// Before ARMv8 the rules for when SP is allowed in t2MOVr are more complex |
10946 |
// Before ARMv8 the rules for when SP is allowed in t2MOVr are more complex |
| 10947 |
// than the loop below can handle, so it uses the GPRnopc register class and |
10947 |
// than the loop below can handle, so it uses the GPRnopc register class and |
| 10948 |
// we do SP handling here. |
10948 |
// we do SP handling here. |
| 10949 |
if (Opc == ARM::t2MOVr && !hasV8Ops()) |
10949 |
if (Opc == ARM::t2MOVr && !hasV8Ops()) |
| 10950 |
{ |
10950 |
{ |
| 10951 |
// SP as both source and destination is not allowed |
10951 |
// SP as both source and destination is not allowed |
| 10952 |
if (Inst.getOperand(0).getReg() == ARM::SP && |
10952 |
if (Inst.getOperand(0).getReg() == ARM::SP && |
| 10953 |
Inst.getOperand(1).getReg() == ARM::SP) |
10953 |
Inst.getOperand(1).getReg() == ARM::SP) |
| 10954 |
return Match_RequiresV8; |
10954 |
return Match_RequiresV8; |
| 10955 |
// When flags-setting SP as either source or destination is not allowed |
10955 |
// When flags-setting SP as either source or destination is not allowed |
| 10956 |
if (Inst.getOperand(4).getReg() == ARM::CPSR && |
10956 |
if (Inst.getOperand(4).getReg() == ARM::CPSR && |
| 10957 |
(Inst.getOperand(0).getReg() == ARM::SP || |
10957 |
(Inst.getOperand(0).getReg() == ARM::SP || |
| 10958 |
Inst.getOperand(1).getReg() == ARM::SP)) |
10958 |
Inst.getOperand(1).getReg() == ARM::SP)) |
| 10959 |
return Match_RequiresV8; |
10959 |
return Match_RequiresV8; |
| 10960 |
} |
10960 |
} |
| 10961 |
|
10961 |
|
| 10962 |
switch (Inst.getOpcode()) { |
10962 |
switch (Inst.getOpcode()) { |
| 10963 |
case ARM::VMRS: |
10963 |
case ARM::VMRS: |
| 10964 |
case ARM::VMSR: |
10964 |
case ARM::VMSR: |
| 10965 |
case ARM::VMRS_FPCXTS: |
10965 |
case ARM::VMRS_FPCXTS: |
| 10966 |
case ARM::VMRS_FPCXTNS: |
10966 |
case ARM::VMRS_FPCXTNS: |
| 10967 |
case ARM::VMSR_FPCXTS: |
10967 |
case ARM::VMSR_FPCXTS: |
| 10968 |
case ARM::VMSR_FPCXTNS: |
10968 |
case ARM::VMSR_FPCXTNS: |
| 10969 |
case ARM::VMRS_FPSCR_NZCVQC: |
10969 |
case ARM::VMRS_FPSCR_NZCVQC: |
| 10970 |
case ARM::VMSR_FPSCR_NZCVQC: |
10970 |
case ARM::VMSR_FPSCR_NZCVQC: |
| 10971 |
case ARM::FMSTAT: |
10971 |
case ARM::FMSTAT: |
| 10972 |
case ARM::VMRS_VPR: |
10972 |
case ARM::VMRS_VPR: |
| 10973 |
case ARM::VMRS_P0: |
10973 |
case ARM::VMRS_P0: |
| 10974 |
case ARM::VMSR_VPR: |
10974 |
case ARM::VMSR_VPR: |
| 10975 |
case ARM::VMSR_P0: |
10975 |
case ARM::VMSR_P0: |
| 10976 |
// Use of SP for VMRS/VMSR is only allowed in ARM mode with the exception of |
10976 |
// Use of SP for VMRS/VMSR is only allowed in ARM mode with the exception of |
| 10977 |
// ARMv8-A. |
10977 |
// ARMv8-A. |
| 10978 |
if (Inst.getOperand(0).isReg() && Inst.getOperand(0).getReg() == ARM::SP && |
10978 |
if (Inst.getOperand(0).isReg() && Inst.getOperand(0).getReg() == ARM::SP && |
| 10979 |
(isThumb() && !hasV8Ops())) |
10979 |
(isThumb() && !hasV8Ops())) |
| 10980 |
return Match_InvalidOperand; |
10980 |
return Match_InvalidOperand; |
| 10981 |
break; |
10981 |
break; |
| 10982 |
case ARM::t2TBB: |
10982 |
case ARM::t2TBB: |
| 10983 |
case ARM::t2TBH: |
10983 |
case ARM::t2TBH: |
| 10984 |
// Rn = sp is only allowed with ARMv8-A |
10984 |
// Rn = sp is only allowed with ARMv8-A |
| 10985 |
if (!hasV8Ops() && (Inst.getOperand(0).getReg() == ARM::SP)) |
10985 |
if (!hasV8Ops() && (Inst.getOperand(0).getReg() == ARM::SP)) |
| 10986 |
return Match_RequiresV8; |
10986 |
return Match_RequiresV8; |
| 10987 |
break; |
10987 |
break; |
| 10988 |
default: |
10988 |
default: |
| 10989 |
break; |
10989 |
break; |
| 10990 |
} |
10990 |
} |
| 10991 |
|
10991 |
|
| 10992 |
for (unsigned I = 0; I < MCID.NumOperands; ++I) |
10992 |
for (unsigned I = 0; I < MCID.NumOperands; ++I) |
| 10993 |
if (MCID.operands()[I].RegClass == ARM::rGPRRegClassID) { |
10993 |
if (MCID.operands()[I].RegClass == ARM::rGPRRegClassID) { |
| 10994 |
// rGPRRegClass excludes PC, and also excluded SP before ARMv8 |
10994 |
// rGPRRegClass excludes PC, and also excluded SP before ARMv8 |
| 10995 |
const auto &Op = Inst.getOperand(I); |
10995 |
const auto &Op = Inst.getOperand(I); |
| 10996 |
if (!Op.isReg()) { |
10996 |
if (!Op.isReg()) { |
| 10997 |
// This can happen in awkward cases with tied operands, e.g. a |
10997 |
// This can happen in awkward cases with tied operands, e.g. a |
| 10998 |
// writeback load/store with a complex addressing mode in |
10998 |
// writeback load/store with a complex addressing mode in |
| 10999 |
// which there's an output operand corresponding to the |
10999 |
// which there's an output operand corresponding to the |
| 11000 |
// updated written-back base register: the Tablegen-generated |
11000 |
// updated written-back base register: the Tablegen-generated |
| 11001 |
// AsmMatcher will have written a placeholder operand to that |
11001 |
// AsmMatcher will have written a placeholder operand to that |
| 11002 |
// slot in the form of an immediate 0, because it can't |
11002 |
// slot in the form of an immediate 0, because it can't |
| 11003 |
// generate the register part of the complex addressing-mode |
11003 |
// generate the register part of the complex addressing-mode |
| 11004 |
// operand ahead of time. |
11004 |
// operand ahead of time. |
| 11005 |
continue; |
11005 |
continue; |
| 11006 |
} |
11006 |
} |
| 11007 |
|
11007 |
|
| 11008 |
unsigned Reg = Op.getReg(); |
11008 |
unsigned Reg = Op.getReg(); |
| 11009 |
if ((Reg == ARM::SP) && !hasV8Ops()) |
11009 |
if ((Reg == ARM::SP) && !hasV8Ops()) |
| 11010 |
return Match_RequiresV8; |
11010 |
return Match_RequiresV8; |
| 11011 |
else if (Reg == ARM::PC) |
11011 |
else if (Reg == ARM::PC) |
| 11012 |
return Match_InvalidOperand; |
11012 |
return Match_InvalidOperand; |
| 11013 |
} |
11013 |
} |
| 11014 |
|
11014 |
|
| 11015 |
return Match_Success; |
11015 |
return Match_Success; |
| 11016 |
} |
11016 |
} |
| 11017 |
|
11017 |
|
| 11018 |
namespace llvm { |
11018 |
namespace llvm { |
| 11019 |
|
11019 |
|
| 11020 |
template <> inline bool IsCPSRDead(const MCInst *Instr) { |
11020 |
template <> inline bool IsCPSRDead(const MCInst *Instr) { |
| 11021 |
return true; // In an assembly source, no need to second-guess |
11021 |
return true; // In an assembly source, no need to second-guess |
| 11022 |
} |
11022 |
} |
| 11023 |
|
11023 |
|
| 11024 |
} // end namespace llvm |
11024 |
} // end namespace llvm |
| 11025 |
|
11025 |
|
| 11026 |
// Returns true if Inst is unpredictable if it is in and IT block, but is not |
11026 |
// Returns true if Inst is unpredictable if it is in and IT block, but is not |
| 11027 |
// the last instruction in the block. |
11027 |
// the last instruction in the block. |
| 11028 |
bool ARMAsmParser::isITBlockTerminator(MCInst &Inst) const { |
11028 |
bool ARMAsmParser::isITBlockTerminator(MCInst &Inst) const { |
| 11029 |
const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); |
11029 |
const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); |
| 11030 |
|
11030 |
|
| 11031 |
// All branch & call instructions terminate IT blocks with the exception of |
11031 |
// All branch & call instructions terminate IT blocks with the exception of |
| 11032 |
// SVC. |
11032 |
// SVC. |
| 11033 |
if (MCID.isTerminator() || (MCID.isCall() && Inst.getOpcode() != ARM::tSVC) || |
11033 |
if (MCID.isTerminator() || (MCID.isCall() && Inst.getOpcode() != ARM::tSVC) || |
| 11034 |
MCID.isReturn() || MCID.isBranch() || MCID.isIndirectBranch()) |
11034 |
MCID.isReturn() || MCID.isBranch() || MCID.isIndirectBranch()) |
| 11035 |
return true; |
11035 |
return true; |
| 11036 |
|
11036 |
|
| 11037 |
// Any arithmetic instruction which writes to the PC also terminates the IT |
11037 |
// Any arithmetic instruction which writes to the PC also terminates the IT |
| 11038 |
// block. |
11038 |
// block. |
| 11039 |
if (MCID.hasDefOfPhysReg(Inst, ARM::PC, *MRI)) |
11039 |
if (MCID.hasDefOfPhysReg(Inst, ARM::PC, *MRI)) |
| 11040 |
return true; |
11040 |
return true; |
| 11041 |
|
11041 |
|
| 11042 |
return false; |
11042 |
return false; |
| 11043 |
} |
11043 |
} |
| 11044 |
|
11044 |
|
| 11045 |
unsigned ARMAsmParser::MatchInstruction(OperandVector &Operands, MCInst &Inst, |
11045 |
unsigned ARMAsmParser::MatchInstruction(OperandVector &Operands, MCInst &Inst, |
| 11046 |
SmallVectorImpl &NearMisses, |
11046 |
SmallVectorImpl &NearMisses, |
| 11047 |
bool MatchingInlineAsm, |
11047 |
bool MatchingInlineAsm, |
| 11048 |
bool &EmitInITBlock, |
11048 |
bool &EmitInITBlock, |
| 11049 |
MCStreamer &Out) { |
11049 |
MCStreamer &Out) { |
| 11050 |
// If we can't use an implicit IT block here, just match as normal. |
11050 |
// If we can't use an implicit IT block here, just match as normal. |
| 11051 |
if (inExplicitITBlock() || !isThumbTwo() || !useImplicitITThumb()) |
11051 |
if (inExplicitITBlock() || !isThumbTwo() || !useImplicitITThumb()) |
| 11052 |
return MatchInstructionImpl(Operands, Inst, &NearMisses, MatchingInlineAsm); |
11052 |
return MatchInstructionImpl(Operands, Inst, &NearMisses, MatchingInlineAsm); |
| 11053 |
|
11053 |
|
| 11054 |
// Try to match the instruction in an extension of the current IT block (if |
11054 |
// Try to match the instruction in an extension of the current IT block (if |
| 11055 |
// there is one). |
11055 |
// there is one). |
| 11056 |
if (inImplicitITBlock()) { |
11056 |
if (inImplicitITBlock()) { |
| 11057 |
extendImplicitITBlock(ITState.Cond); |
11057 |
extendImplicitITBlock(ITState.Cond); |
| 11058 |
if (MatchInstructionImpl(Operands, Inst, nullptr, MatchingInlineAsm) == |
11058 |
if (MatchInstructionImpl(Operands, Inst, nullptr, MatchingInlineAsm) == |
| 11059 |
Match_Success) { |
11059 |
Match_Success) { |
| 11060 |
// The match succeded, but we still have to check that the instruction is |
11060 |
// The match succeded, but we still have to check that the instruction is |
| 11061 |
// valid in this implicit IT block. |
11061 |
// valid in this implicit IT block. |
| 11062 |
const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); |
11062 |
const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); |
| 11063 |
if (MCID.isPredicable()) { |
11063 |
if (MCID.isPredicable()) { |
| 11064 |
ARMCC::CondCodes InstCond = |
11064 |
ARMCC::CondCodes InstCond = |
| 11065 |
(ARMCC::CondCodes)Inst.getOperand(MCID.findFirstPredOperandIdx()) |
11065 |
(ARMCC::CondCodes)Inst.getOperand(MCID.findFirstPredOperandIdx()) |
| 11066 |
.getImm(); |
11066 |
.getImm(); |
| 11067 |
ARMCC::CondCodes ITCond = currentITCond(); |
11067 |
ARMCC::CondCodes ITCond = currentITCond(); |
| 11068 |
if (InstCond == ITCond) { |
11068 |
if (InstCond == ITCond) { |
| 11069 |
EmitInITBlock = true; |
11069 |
EmitInITBlock = true; |
| 11070 |
return Match_Success; |
11070 |
return Match_Success; |
| 11071 |
} else if (InstCond == ARMCC::getOppositeCondition(ITCond)) { |
11071 |
} else if (InstCond == ARMCC::getOppositeCondition(ITCond)) { |
| 11072 |
invertCurrentITCondition(); |
11072 |
invertCurrentITCondition(); |
| 11073 |
EmitInITBlock = true; |
11073 |
EmitInITBlock = true; |
| 11074 |
return Match_Success; |
11074 |
return Match_Success; |
| 11075 |
} |
11075 |
} |
| 11076 |
} |
11076 |
} |
| 11077 |
} |
11077 |
} |
| 11078 |
rewindImplicitITPosition(); |
11078 |
rewindImplicitITPosition(); |
| 11079 |
} |
11079 |
} |
| 11080 |
|
11080 |
|
| 11081 |
// Finish the current IT block, and try to match outside any IT block. |
11081 |
// Finish the current IT block, and try to match outside any IT block. |
| 11082 |
flushPendingInstructions(Out); |
11082 |
flushPendingInstructions(Out); |
| 11083 |
unsigned PlainMatchResult = |
11083 |
unsigned PlainMatchResult = |
| 11084 |
MatchInstructionImpl(Operands, Inst, &NearMisses, MatchingInlineAsm); |
11084 |
MatchInstructionImpl(Operands, Inst, &NearMisses, MatchingInlineAsm); |
| 11085 |
if (PlainMatchResult == Match_Success) { |
11085 |
if (PlainMatchResult == Match_Success) { |
| 11086 |
const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); |
11086 |
const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); |
| 11087 |
if (MCID.isPredicable()) { |
11087 |
if (MCID.isPredicable()) { |
| 11088 |
ARMCC::CondCodes InstCond = |
11088 |
ARMCC::CondCodes InstCond = |
| 11089 |
(ARMCC::CondCodes)Inst.getOperand(MCID.findFirstPredOperandIdx()) |
11089 |
(ARMCC::CondCodes)Inst.getOperand(MCID.findFirstPredOperandIdx()) |
| 11090 |
.getImm(); |
11090 |
.getImm(); |
| 11091 |
// Some forms of the branch instruction have their own condition code |
11091 |
// Some forms of the branch instruction have their own condition code |
| 11092 |
// fields, so can be conditionally executed without an IT block. |
11092 |
// fields, so can be conditionally executed without an IT block. |
| 11093 |
if (Inst.getOpcode() == ARM::tBcc || Inst.getOpcode() == ARM::t2Bcc) { |
11093 |
if (Inst.getOpcode() == ARM::tBcc || Inst.getOpcode() == ARM::t2Bcc) { |
| 11094 |
EmitInITBlock = false; |
11094 |
EmitInITBlock = false; |
| 11095 |
return Match_Success; |
11095 |
return Match_Success; |
| 11096 |
} |
11096 |
} |
| 11097 |
if (InstCond == ARMCC::AL) { |
11097 |
if (InstCond == ARMCC::AL) { |
| 11098 |
EmitInITBlock = false; |
11098 |
EmitInITBlock = false; |
| 11099 |
return Match_Success; |
11099 |
return Match_Success; |
| 11100 |
} |
11100 |
} |
| 11101 |
} else { |
11101 |
} else { |
| 11102 |
EmitInITBlock = false; |
11102 |
EmitInITBlock = false; |
| 11103 |
return Match_Success; |
11103 |
return Match_Success; |
| 11104 |
} |
11104 |
} |
| 11105 |
} |
11105 |
} |
| 11106 |
|
11106 |
|
| 11107 |
// Try to match in a new IT block. The matcher doesn't check the actual |
11107 |
// Try to match in a new IT block. The matcher doesn't check the actual |
| 11108 |
// condition, so we create an IT block with a dummy condition, and fix it up |
11108 |
// condition, so we create an IT block with a dummy condition, and fix it up |
| 11109 |
// once we know the actual condition. |
11109 |
// once we know the actual condition. |
| 11110 |
startImplicitITBlock(); |
11110 |
startImplicitITBlock(); |
| 11111 |
if (MatchInstructionImpl(Operands, Inst, nullptr, MatchingInlineAsm) == |
11111 |
if (MatchInstructionImpl(Operands, Inst, nullptr, MatchingInlineAsm) == |
| 11112 |
Match_Success) { |
11112 |
Match_Success) { |
| 11113 |
const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); |
11113 |
const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); |
| 11114 |
if (MCID.isPredicable()) { |
11114 |
if (MCID.isPredicable()) { |
| 11115 |
ITState.Cond = |
11115 |
ITState.Cond = |
| 11116 |
(ARMCC::CondCodes)Inst.getOperand(MCID.findFirstPredOperandIdx()) |
11116 |
(ARMCC::CondCodes)Inst.getOperand(MCID.findFirstPredOperandIdx()) |
| 11117 |
.getImm(); |
11117 |
.getImm(); |
| 11118 |
EmitInITBlock = true; |
11118 |
EmitInITBlock = true; |
| 11119 |
return Match_Success; |
11119 |
return Match_Success; |
| 11120 |
} |
11120 |
} |
| 11121 |
} |
11121 |
} |
| 11122 |
discardImplicitITBlock(); |
11122 |
discardImplicitITBlock(); |
| 11123 |
|
11123 |
|
| 11124 |
// If none of these succeed, return the error we got when trying to match |
11124 |
// If none of these succeed, return the error we got when trying to match |
| 11125 |
// outside any IT blocks. |
11125 |
// outside any IT blocks. |
| 11126 |
EmitInITBlock = false; |
11126 |
EmitInITBlock = false; |
| 11127 |
return PlainMatchResult; |
11127 |
return PlainMatchResult; |
| 11128 |
} |
11128 |
} |
| 11129 |
|
11129 |
|
| 11130 |
static std::string ARMMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, |
11130 |
static std::string ARMMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, |
| 11131 |
unsigned VariantID = 0); |
11131 |
unsigned VariantID = 0); |
| 11132 |
|
11132 |
|
| 11133 |
static const char *getSubtargetFeatureName(uint64_t Val); |
11133 |
static const char *getSubtargetFeatureName(uint64_t Val); |
| 11134 |
bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
11134 |
bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
| 11135 |
OperandVector &Operands, |
11135 |
OperandVector &Operands, |
| 11136 |
MCStreamer &Out, uint64_t &ErrorInfo, |
11136 |
MCStreamer &Out, uint64_t &ErrorInfo, |
| 11137 |
bool MatchingInlineAsm) { |
11137 |
bool MatchingInlineAsm) { |
| 11138 |
MCInst Inst; |
11138 |
MCInst Inst; |
| 11139 |
unsigned MatchResult; |
11139 |
unsigned MatchResult; |
| 11140 |
bool PendConditionalInstruction = false; |
11140 |
bool PendConditionalInstruction = false; |
| 11141 |
|
11141 |
|
| 11142 |
SmallVector NearMisses; |
11142 |
SmallVector NearMisses; |
| 11143 |
MatchResult = MatchInstruction(Operands, Inst, NearMisses, MatchingInlineAsm, |
11143 |
MatchResult = MatchInstruction(Operands, Inst, NearMisses, MatchingInlineAsm, |
| 11144 |
PendConditionalInstruction, Out); |
11144 |
PendConditionalInstruction, Out); |
| 11145 |
|
11145 |
|
| 11146 |
switch (MatchResult) { |
11146 |
switch (MatchResult) { |
| 11147 |
case Match_Success: |
11147 |
case Match_Success: |
| 11148 |
LLVM_DEBUG(dbgs() << "Parsed as: "; |
11148 |
LLVM_DEBUG(dbgs() << "Parsed as: "; |
| 11149 |
Inst.dump_pretty(dbgs(), MII.getName(Inst.getOpcode())); |
11149 |
Inst.dump_pretty(dbgs(), MII.getName(Inst.getOpcode())); |
| 11150 |
dbgs() << "\n"); |
11150 |
dbgs() << "\n"); |
| 11151 |
|
11151 |
|
| 11152 |
// Context sensitive operand constraints aren't handled by the matcher, |
11152 |
// Context sensitive operand constraints aren't handled by the matcher, |
| 11153 |
// so check them here. |
11153 |
// so check them here. |
| 11154 |
if (validateInstruction(Inst, Operands)) { |
11154 |
if (validateInstruction(Inst, Operands)) { |
| 11155 |
// Still progress the IT block, otherwise one wrong condition causes |
11155 |
// Still progress the IT block, otherwise one wrong condition causes |
| 11156 |
// nasty cascading errors. |
11156 |
// nasty cascading errors. |
| 11157 |
forwardITPosition(); |
11157 |
forwardITPosition(); |
| 11158 |
forwardVPTPosition(); |
11158 |
forwardVPTPosition(); |
| 11159 |
return true; |
11159 |
return true; |
| 11160 |
} |
11160 |
} |
| 11161 |
|
11161 |
|
| 11162 |
{ |
11162 |
{ |
| 11163 |
// Some instructions need post-processing to, for example, tweak which |
11163 |
// Some instructions need post-processing to, for example, tweak which |
| 11164 |
// encoding is selected. Loop on it while changes happen so the |
11164 |
// encoding is selected. Loop on it while changes happen so the |
| 11165 |
// individual transformations can chain off each other. E.g., |
11165 |
// individual transformations can chain off each other. E.g., |
| 11166 |
// tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8) |
11166 |
// tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8) |
| 11167 |
while (processInstruction(Inst, Operands, Out)) |
11167 |
while (processInstruction(Inst, Operands, Out)) |
| 11168 |
LLVM_DEBUG(dbgs() << "Changed to: "; |
11168 |
LLVM_DEBUG(dbgs() << "Changed to: "; |
| 11169 |
Inst.dump_pretty(dbgs(), MII.getName(Inst.getOpcode())); |
11169 |
Inst.dump_pretty(dbgs(), MII.getName(Inst.getOpcode())); |
| 11170 |
dbgs() << "\n"); |
11170 |
dbgs() << "\n"); |
| 11171 |
} |
11171 |
} |
| 11172 |
|
11172 |
|
| 11173 |
// Only move forward at the very end so that everything in validate |
11173 |
// Only move forward at the very end so that everything in validate |
| 11174 |
// and process gets a consistent answer about whether we're in an IT |
11174 |
// and process gets a consistent answer about whether we're in an IT |
| 11175 |
// block. |
11175 |
// block. |
| 11176 |
forwardITPosition(); |
11176 |
forwardITPosition(); |
| 11177 |
forwardVPTPosition(); |
11177 |
forwardVPTPosition(); |
| 11178 |
|
11178 |
|
| 11179 |
// ITasm is an ARM mode pseudo-instruction that just sets the ITblock and |
11179 |
// ITasm is an ARM mode pseudo-instruction that just sets the ITblock and |
| 11180 |
// doesn't actually encode. |
11180 |
// doesn't actually encode. |
| 11181 |
if (Inst.getOpcode() == ARM::ITasm) |
11181 |
if (Inst.getOpcode() == ARM::ITasm) |
| 11182 |
return false; |
11182 |
return false; |
| 11183 |
|
11183 |
|
| 11184 |
Inst.setLoc(IDLoc); |
11184 |
Inst.setLoc(IDLoc); |
| 11185 |
if (PendConditionalInstruction) { |
11185 |
if (PendConditionalInstruction) { |
| 11186 |
PendingConditionalInsts.push_back(Inst); |
11186 |
PendingConditionalInsts.push_back(Inst); |
| 11187 |
if (isITBlockFull() || isITBlockTerminator(Inst)) |
11187 |
if (isITBlockFull() || isITBlockTerminator(Inst)) |
| 11188 |
flushPendingInstructions(Out); |
11188 |
flushPendingInstructions(Out); |
| 11189 |
} else { |
11189 |
} else { |
| 11190 |
Out.emitInstruction(Inst, getSTI()); |
11190 |
Out.emitInstruction(Inst, getSTI()); |
| 11191 |
} |
11191 |
} |
| 11192 |
return false; |
11192 |
return false; |
| 11193 |
case Match_NearMisses: |
11193 |
case Match_NearMisses: |
| 11194 |
ReportNearMisses(NearMisses, IDLoc, Operands); |
11194 |
ReportNearMisses(NearMisses, IDLoc, Operands); |
| 11195 |
return true; |
11195 |
return true; |
| 11196 |
case Match_MnemonicFail: { |
11196 |
case Match_MnemonicFail: { |
| 11197 |
FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); |
11197 |
FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); |
| 11198 |
std::string Suggestion = ARMMnemonicSpellCheck( |
11198 |
std::string Suggestion = ARMMnemonicSpellCheck( |
| 11199 |
((ARMOperand &)*Operands[0]).getToken(), FBS); |
11199 |
((ARMOperand &)*Operands[0]).getToken(), FBS); |
| 11200 |
return Error(IDLoc, "invalid instruction" + Suggestion, |
11200 |
return Error(IDLoc, "invalid instruction" + Suggestion, |
| 11201 |
((ARMOperand &)*Operands[0]).getLocRange()); |
11201 |
((ARMOperand &)*Operands[0]).getLocRange()); |
| 11202 |
} |
11202 |
} |
| 11203 |
} |
11203 |
} |
| 11204 |
|
11204 |
|
| 11205 |
llvm_unreachable("Implement any new match types added!"); |
11205 |
llvm_unreachable("Implement any new match types added!"); |
| 11206 |
} |
11206 |
} |
| 11207 |
|
11207 |
|
| 11208 |
/// parseDirective parses the arm specific directives |
11208 |
/// parseDirective parses the arm specific directives |
| 11209 |
bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { |
11209 |
bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { |
| 11210 |
const MCContext::Environment Format = getContext().getObjectFileType(); |
11210 |
const MCContext::Environment Format = getContext().getObjectFileType(); |
| 11211 |
bool IsMachO = Format == MCContext::IsMachO; |
11211 |
bool IsMachO = Format == MCContext::IsMachO; |
| 11212 |
bool IsCOFF = Format == MCContext::IsCOFF; |
11212 |
bool IsCOFF = Format == MCContext::IsCOFF; |
| 11213 |
|
11213 |
|
| 11214 |
std::string IDVal = DirectiveID.getIdentifier().lower(); |
11214 |
std::string IDVal = DirectiveID.getIdentifier().lower(); |
| 11215 |
if (IDVal == ".word") |
11215 |
if (IDVal == ".word") |
| 11216 |
parseLiteralValues(4, DirectiveID.getLoc()); |
11216 |
parseLiteralValues(4, DirectiveID.getLoc()); |
| 11217 |
else if (IDVal == ".short" || IDVal == ".hword") |
11217 |
else if (IDVal == ".short" || IDVal == ".hword") |
| 11218 |
parseLiteralValues(2, DirectiveID.getLoc()); |
11218 |
parseLiteralValues(2, DirectiveID.getLoc()); |
| 11219 |
else if (IDVal == ".thumb") |
11219 |
else if (IDVal == ".thumb") |
| 11220 |
parseDirectiveThumb(DirectiveID.getLoc()); |
11220 |
parseDirectiveThumb(DirectiveID.getLoc()); |
| 11221 |
else if (IDVal == ".arm") |
11221 |
else if (IDVal == ".arm") |
| 11222 |
parseDirectiveARM(DirectiveID.getLoc()); |
11222 |
parseDirectiveARM(DirectiveID.getLoc()); |
| 11223 |
else if (IDVal == ".thumb_func") |
11223 |
else if (IDVal == ".thumb_func") |
| 11224 |
parseDirectiveThumbFunc(DirectiveID.getLoc()); |
11224 |
parseDirectiveThumbFunc(DirectiveID.getLoc()); |
| 11225 |
else if (IDVal == ".code") |
11225 |
else if (IDVal == ".code") |
| 11226 |
parseDirectiveCode(DirectiveID.getLoc()); |
11226 |
parseDirectiveCode(DirectiveID.getLoc()); |
| 11227 |
else if (IDVal == ".syntax") |
11227 |
else if (IDVal == ".syntax") |
| 11228 |
parseDirectiveSyntax(DirectiveID.getLoc()); |
11228 |
parseDirectiveSyntax(DirectiveID.getLoc()); |
| 11229 |
else if (IDVal == ".unreq") |
11229 |
else if (IDVal == ".unreq") |
| 11230 |
parseDirectiveUnreq(DirectiveID.getLoc()); |
11230 |
parseDirectiveUnreq(DirectiveID.getLoc()); |
| 11231 |
else if (IDVal == ".fnend") |
11231 |
else if (IDVal == ".fnend") |
| 11232 |
parseDirectiveFnEnd(DirectiveID.getLoc()); |
11232 |
parseDirectiveFnEnd(DirectiveID.getLoc()); |
| 11233 |
else if (IDVal == ".cantunwind") |
11233 |
else if (IDVal == ".cantunwind") |
| 11234 |
parseDirectiveCantUnwind(DirectiveID.getLoc()); |
11234 |
parseDirectiveCantUnwind(DirectiveID.getLoc()); |
| 11235 |
else if (IDVal == ".personality") |
11235 |
else if (IDVal == ".personality") |
| 11236 |
parseDirectivePersonality(DirectiveID.getLoc()); |
11236 |
parseDirectivePersonality(DirectiveID.getLoc()); |
| 11237 |
else if (IDVal == ".handlerdata") |
11237 |
else if (IDVal == ".handlerdata") |
| 11238 |
parseDirectiveHandlerData(DirectiveID.getLoc()); |
11238 |
parseDirectiveHandlerData(DirectiveID.getLoc()); |
| 11239 |
else if (IDVal == ".setfp") |
11239 |
else if (IDVal == ".setfp") |
| 11240 |
parseDirectiveSetFP(DirectiveID.getLoc()); |
11240 |
parseDirectiveSetFP(DirectiveID.getLoc()); |
| 11241 |
else if (IDVal == ".pad") |
11241 |
else if (IDVal == ".pad") |
| 11242 |
parseDirectivePad(DirectiveID.getLoc()); |
11242 |
parseDirectivePad(DirectiveID.getLoc()); |
| 11243 |
else if (IDVal == ".save") |
11243 |
else if (IDVal == ".save") |
| 11244 |
parseDirectiveRegSave(DirectiveID.getLoc(), false); |
11244 |
parseDirectiveRegSave(DirectiveID.getLoc(), false); |
| 11245 |
else if (IDVal == ".vsave") |
11245 |
else if (IDVal == ".vsave") |
| 11246 |
parseDirectiveRegSave(DirectiveID.getLoc(), true); |
11246 |
parseDirectiveRegSave(DirectiveID.getLoc(), true); |
| 11247 |
else if (IDVal == ".ltorg" || IDVal == ".pool") |
11247 |
else if (IDVal == ".ltorg" || IDVal == ".pool") |
| 11248 |
parseDirectiveLtorg(DirectiveID.getLoc()); |
11248 |
parseDirectiveLtorg(DirectiveID.getLoc()); |
| 11249 |
else if (IDVal == ".even") |
11249 |
else if (IDVal == ".even") |
| 11250 |
parseDirectiveEven(DirectiveID.getLoc()); |
11250 |
parseDirectiveEven(DirectiveID.getLoc()); |
| 11251 |
else if (IDVal == ".personalityindex") |
11251 |
else if (IDVal == ".personalityindex") |
| 11252 |
parseDirectivePersonalityIndex(DirectiveID.getLoc()); |
11252 |
parseDirectivePersonalityIndex(DirectiveID.getLoc()); |
| 11253 |
else if (IDVal == ".unwind_raw") |
11253 |
else if (IDVal == ".unwind_raw") |
| 11254 |
parseDirectiveUnwindRaw(DirectiveID.getLoc()); |
11254 |
parseDirectiveUnwindRaw(DirectiveID.getLoc()); |
| 11255 |
else if (IDVal == ".movsp") |
11255 |
else if (IDVal == ".movsp") |
| 11256 |
parseDirectiveMovSP(DirectiveID.getLoc()); |
11256 |
parseDirectiveMovSP(DirectiveID.getLoc()); |
| 11257 |
else if (IDVal == ".arch_extension") |
11257 |
else if (IDVal == ".arch_extension") |
| 11258 |
parseDirectiveArchExtension(DirectiveID.getLoc()); |
11258 |
parseDirectiveArchExtension(DirectiveID.getLoc()); |
| 11259 |
else if (IDVal == ".align") |
11259 |
else if (IDVal == ".align") |
| 11260 |
return parseDirectiveAlign(DirectiveID.getLoc()); // Use Generic on failure. |
11260 |
return parseDirectiveAlign(DirectiveID.getLoc()); // Use Generic on failure. |
| 11261 |
else if (IDVal == ".thumb_set") |
11261 |
else if (IDVal == ".thumb_set") |
| 11262 |
parseDirectiveThumbSet(DirectiveID.getLoc()); |
11262 |
parseDirectiveThumbSet(DirectiveID.getLoc()); |
| 11263 |
else if (IDVal == ".inst") |
11263 |
else if (IDVal == ".inst") |
| 11264 |
parseDirectiveInst(DirectiveID.getLoc()); |
11264 |
parseDirectiveInst(DirectiveID.getLoc()); |
| 11265 |
else if (IDVal == ".inst.n") |
11265 |
else if (IDVal == ".inst.n") |
| 11266 |
parseDirectiveInst(DirectiveID.getLoc(), 'n'); |
11266 |
parseDirectiveInst(DirectiveID.getLoc(), 'n'); |
| 11267 |
else if (IDVal == ".inst.w") |
11267 |
else if (IDVal == ".inst.w") |
| 11268 |
parseDirectiveInst(DirectiveID.getLoc(), 'w'); |
11268 |
parseDirectiveInst(DirectiveID.getLoc(), 'w'); |
| 11269 |
else if (!IsMachO && !IsCOFF) { |
11269 |
else if (!IsMachO && !IsCOFF) { |
| 11270 |
if (IDVal == ".arch") |
11270 |
if (IDVal == ".arch") |
| 11271 |
parseDirectiveArch(DirectiveID.getLoc()); |
11271 |
parseDirectiveArch(DirectiveID.getLoc()); |
| 11272 |
else if (IDVal == ".cpu") |
11272 |
else if (IDVal == ".cpu") |
| 11273 |
parseDirectiveCPU(DirectiveID.getLoc()); |
11273 |
parseDirectiveCPU(DirectiveID.getLoc()); |
| 11274 |
else if (IDVal == ".eabi_attribute") |
11274 |
else if (IDVal == ".eabi_attribute") |
| 11275 |
parseDirectiveEabiAttr(DirectiveID.getLoc()); |
11275 |
parseDirectiveEabiAttr(DirectiveID.getLoc()); |
| 11276 |
else if (IDVal == ".fpu") |
11276 |
else if (IDVal == ".fpu") |
| 11277 |
parseDirectiveFPU(DirectiveID.getLoc()); |
11277 |
parseDirectiveFPU(DirectiveID.getLoc()); |
| 11278 |
else if (IDVal == ".fnstart") |
11278 |
else if (IDVal == ".fnstart") |
| 11279 |
parseDirectiveFnStart(DirectiveID.getLoc()); |
11279 |
parseDirectiveFnStart(DirectiveID.getLoc()); |
| 11280 |
else if (IDVal == ".object_arch") |
11280 |
else if (IDVal == ".object_arch") |
| 11281 |
parseDirectiveObjectArch(DirectiveID.getLoc()); |
11281 |
parseDirectiveObjectArch(DirectiveID.getLoc()); |
| 11282 |
else if (IDVal == ".tlsdescseq") |
11282 |
else if (IDVal == ".tlsdescseq") |
| 11283 |
parseDirectiveTLSDescSeq(DirectiveID.getLoc()); |
11283 |
parseDirectiveTLSDescSeq(DirectiveID.getLoc()); |
| 11284 |
else |
11284 |
else |
| 11285 |
return true; |
11285 |
return true; |
| 11286 |
} else if (IsCOFF) { |
11286 |
} else if (IsCOFF) { |
| 11287 |
if (IDVal == ".seh_stackalloc") |
11287 |
if (IDVal == ".seh_stackalloc") |
| 11288 |
parseDirectiveSEHAllocStack(DirectiveID.getLoc(), /*Wide=*/false); |
11288 |
parseDirectiveSEHAllocStack(DirectiveID.getLoc(), /*Wide=*/false); |
| 11289 |
else if (IDVal == ".seh_stackalloc_w") |
11289 |
else if (IDVal == ".seh_stackalloc_w") |
| 11290 |
parseDirectiveSEHAllocStack(DirectiveID.getLoc(), /*Wide=*/true); |
11290 |
parseDirectiveSEHAllocStack(DirectiveID.getLoc(), /*Wide=*/true); |
| 11291 |
else if (IDVal == ".seh_save_regs") |
11291 |
else if (IDVal == ".seh_save_regs") |
| 11292 |
parseDirectiveSEHSaveRegs(DirectiveID.getLoc(), /*Wide=*/false); |
11292 |
parseDirectiveSEHSaveRegs(DirectiveID.getLoc(), /*Wide=*/false); |
| 11293 |
else if (IDVal == ".seh_save_regs_w") |
11293 |
else if (IDVal == ".seh_save_regs_w") |
| 11294 |
parseDirectiveSEHSaveRegs(DirectiveID.getLoc(), /*Wide=*/true); |
11294 |
parseDirectiveSEHSaveRegs(DirectiveID.getLoc(), /*Wide=*/true); |
| 11295 |
else if (IDVal == ".seh_save_sp") |
11295 |
else if (IDVal == ".seh_save_sp") |
| 11296 |
parseDirectiveSEHSaveSP(DirectiveID.getLoc()); |
11296 |
parseDirectiveSEHSaveSP(DirectiveID.getLoc()); |
| 11297 |
else if (IDVal == ".seh_save_fregs") |
11297 |
else if (IDVal == ".seh_save_fregs") |
| 11298 |
parseDirectiveSEHSaveFRegs(DirectiveID.getLoc()); |
11298 |
parseDirectiveSEHSaveFRegs(DirectiveID.getLoc()); |
| 11299 |
else if (IDVal == ".seh_save_lr") |
11299 |
else if (IDVal == ".seh_save_lr") |
| 11300 |
parseDirectiveSEHSaveLR(DirectiveID.getLoc()); |
11300 |
parseDirectiveSEHSaveLR(DirectiveID.getLoc()); |
| 11301 |
else if (IDVal == ".seh_endprologue") |
11301 |
else if (IDVal == ".seh_endprologue") |
| 11302 |
parseDirectiveSEHPrologEnd(DirectiveID.getLoc(), /*Fragment=*/false); |
11302 |
parseDirectiveSEHPrologEnd(DirectiveID.getLoc(), /*Fragment=*/false); |
| 11303 |
else if (IDVal == ".seh_endprologue_fragment") |
11303 |
else if (IDVal == ".seh_endprologue_fragment") |
| 11304 |
parseDirectiveSEHPrologEnd(DirectiveID.getLoc(), /*Fragment=*/true); |
11304 |
parseDirectiveSEHPrologEnd(DirectiveID.getLoc(), /*Fragment=*/true); |
| 11305 |
else if (IDVal == ".seh_nop") |
11305 |
else if (IDVal == ".seh_nop") |
| 11306 |
parseDirectiveSEHNop(DirectiveID.getLoc(), /*Wide=*/false); |
11306 |
parseDirectiveSEHNop(DirectiveID.getLoc(), /*Wide=*/false); |
| 11307 |
else if (IDVal == ".seh_nop_w") |
11307 |
else if (IDVal == ".seh_nop_w") |
| 11308 |
parseDirectiveSEHNop(DirectiveID.getLoc(), /*Wide=*/true); |
11308 |
parseDirectiveSEHNop(DirectiveID.getLoc(), /*Wide=*/true); |
| 11309 |
else if (IDVal == ".seh_startepilogue") |
11309 |
else if (IDVal == ".seh_startepilogue") |
| 11310 |
parseDirectiveSEHEpilogStart(DirectiveID.getLoc(), /*Condition=*/false); |
11310 |
parseDirectiveSEHEpilogStart(DirectiveID.getLoc(), /*Condition=*/false); |
| 11311 |
else if (IDVal == ".seh_startepilogue_cond") |
11311 |
else if (IDVal == ".seh_startepilogue_cond") |
| 11312 |
parseDirectiveSEHEpilogStart(DirectiveID.getLoc(), /*Condition=*/true); |
11312 |
parseDirectiveSEHEpilogStart(DirectiveID.getLoc(), /*Condition=*/true); |
| 11313 |
else if (IDVal == ".seh_endepilogue") |
11313 |
else if (IDVal == ".seh_endepilogue") |
| 11314 |
parseDirectiveSEHEpilogEnd(DirectiveID.getLoc()); |
11314 |
parseDirectiveSEHEpilogEnd(DirectiveID.getLoc()); |
| 11315 |
else if (IDVal == ".seh_custom") |
11315 |
else if (IDVal == ".seh_custom") |
| 11316 |
parseDirectiveSEHCustom(DirectiveID.getLoc()); |
11316 |
parseDirectiveSEHCustom(DirectiveID.getLoc()); |
| 11317 |
else |
11317 |
else |
| 11318 |
return true; |
11318 |
return true; |
| 11319 |
} else |
11319 |
} else |
| 11320 |
return true; |
11320 |
return true; |
| 11321 |
return false; |
11321 |
return false; |
| 11322 |
} |
11322 |
} |
| 11323 |
|
11323 |
|
| 11324 |
/// parseLiteralValues |
11324 |
/// parseLiteralValues |
| 11325 |
/// ::= .hword expression [, expression]* |
11325 |
/// ::= .hword expression [, expression]* |
| 11326 |
/// ::= .short expression [, expression]* |
11326 |
/// ::= .short expression [, expression]* |
| 11327 |
/// ::= .word expression [, expression]* |
11327 |
/// ::= .word expression [, expression]* |
| 11328 |
bool ARMAsmParser::parseLiteralValues(unsigned Size, SMLoc L) { |
11328 |
bool ARMAsmParser::parseLiteralValues(unsigned Size, SMLoc L) { |
| 11329 |
auto parseOne = [&]() -> bool { |
11329 |
auto parseOne = [&]() -> bool { |
| 11330 |
const MCExpr *Value; |
11330 |
const MCExpr *Value; |
| 11331 |
if (getParser().parseExpression(Value)) |
11331 |
if (getParser().parseExpression(Value)) |
| 11332 |
return true; |
11332 |
return true; |
| 11333 |
getParser().getStreamer().emitValue(Value, Size, L); |
11333 |
getParser().getStreamer().emitValue(Value, Size, L); |
| 11334 |
return false; |
11334 |
return false; |
| 11335 |
}; |
11335 |
}; |
| 11336 |
return (parseMany(parseOne)); |
11336 |
return (parseMany(parseOne)); |
| 11337 |
} |
11337 |
} |
| 11338 |
|
11338 |
|
| 11339 |
/// parseDirectiveThumb |
11339 |
/// parseDirectiveThumb |
| 11340 |
/// ::= .thumb |
11340 |
/// ::= .thumb |
| 11341 |
bool ARMAsmParser::parseDirectiveThumb(SMLoc L) { |
11341 |
bool ARMAsmParser::parseDirectiveThumb(SMLoc L) { |
| 11342 |
if (parseEOL() || check(!hasThumb(), L, "target does not support Thumb mode")) |
11342 |
if (parseEOL() || check(!hasThumb(), L, "target does not support Thumb mode")) |
| 11343 |
return true; |
11343 |
return true; |
| 11344 |
|
11344 |
|
| 11345 |
if (!isThumb()) |
11345 |
if (!isThumb()) |
| 11346 |
SwitchMode(); |
11346 |
SwitchMode(); |
| 11347 |
|
11347 |
|
| 11348 |
getParser().getStreamer().emitAssemblerFlag(MCAF_Code16); |
11348 |
getParser().getStreamer().emitAssemblerFlag(MCAF_Code16); |
| 11349 |
getParser().getStreamer().emitCodeAlignment(Align(2), &getSTI(), 0); |
11349 |
getParser().getStreamer().emitCodeAlignment(Align(2), &getSTI(), 0); |
| 11350 |
return false; |
11350 |
return false; |
| 11351 |
} |
11351 |
} |
| 11352 |
|
11352 |
|
| 11353 |
/// parseDirectiveARM |
11353 |
/// parseDirectiveARM |
| 11354 |
/// ::= .arm |
11354 |
/// ::= .arm |
| 11355 |
bool ARMAsmParser::parseDirectiveARM(SMLoc L) { |
11355 |
bool ARMAsmParser::parseDirectiveARM(SMLoc L) { |
| 11356 |
if (parseEOL() || check(!hasARM(), L, "target does not support ARM mode")) |
11356 |
if (parseEOL() || check(!hasARM(), L, "target does not support ARM mode")) |
| 11357 |
return true; |
11357 |
return true; |
| 11358 |
|
11358 |
|
| 11359 |
if (isThumb()) |
11359 |
if (isThumb()) |
| 11360 |
SwitchMode(); |
11360 |
SwitchMode(); |
| 11361 |
getParser().getStreamer().emitAssemblerFlag(MCAF_Code32); |
11361 |
getParser().getStreamer().emitAssemblerFlag(MCAF_Code32); |
| 11362 |
getParser().getStreamer().emitCodeAlignment(Align(4), &getSTI(), 0); |
11362 |
getParser().getStreamer().emitCodeAlignment(Align(4), &getSTI(), 0); |
| 11363 |
return false; |
11363 |
return false; |
| 11364 |
} |
11364 |
} |
| 11365 |
|
11365 |
|
| 11366 |
void ARMAsmParser::doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) { |
11366 |
void ARMAsmParser::doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) { |
| 11367 |
// We need to flush the current implicit IT block on a label, because it is |
11367 |
// We need to flush the current implicit IT block on a label, because it is |
| 11368 |
// not legal to branch into an IT block. |
11368 |
// not legal to branch into an IT block. |
| 11369 |
flushPendingInstructions(getStreamer()); |
11369 |
flushPendingInstructions(getStreamer()); |
| 11370 |
} |
11370 |
} |
| 11371 |
|
11371 |
|
| 11372 |
void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) { |
11372 |
void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) { |
| 11373 |
if (NextSymbolIsThumb) { |
11373 |
if (NextSymbolIsThumb) { |
| 11374 |
getParser().getStreamer().emitThumbFunc(Symbol); |
11374 |
getParser().getStreamer().emitThumbFunc(Symbol); |
| 11375 |
NextSymbolIsThumb = false; |
11375 |
NextSymbolIsThumb = false; |
| 11376 |
} |
11376 |
} |
| 11377 |
} |
11377 |
} |
| 11378 |
|
11378 |
|
| 11379 |
/// parseDirectiveThumbFunc |
11379 |
/// parseDirectiveThumbFunc |
| 11380 |
/// ::= .thumbfunc symbol_name |
11380 |
/// ::= .thumbfunc symbol_name |
| 11381 |
bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { |
11381 |
bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { |
| 11382 |
MCAsmParser &Parser = getParser(); |
11382 |
MCAsmParser &Parser = getParser(); |
| 11383 |
const auto Format = getContext().getObjectFileType(); |
11383 |
const auto Format = getContext().getObjectFileType(); |
| 11384 |
bool IsMachO = Format == MCContext::IsMachO; |
11384 |
bool IsMachO = Format == MCContext::IsMachO; |
| 11385 |
|
11385 |
|
| 11386 |
// Darwin asm has (optionally) function name after .thumb_func direction |
11386 |
// Darwin asm has (optionally) function name after .thumb_func direction |
| 11387 |
// ELF doesn't |
11387 |
// ELF doesn't |
| 11388 |
|
11388 |
|
| 11389 |
if (IsMachO) { |
11389 |
if (IsMachO) { |
| 11390 |
if (Parser.getTok().is(AsmToken::Identifier) || |
11390 |
if (Parser.getTok().is(AsmToken::Identifier) || |
| 11391 |
Parser.getTok().is(AsmToken::String)) { |
11391 |
Parser.getTok().is(AsmToken::String)) { |
| 11392 |
MCSymbol *Func = getParser().getContext().getOrCreateSymbol( |
11392 |
MCSymbol *Func = getParser().getContext().getOrCreateSymbol( |
| 11393 |
Parser.getTok().getIdentifier()); |
11393 |
Parser.getTok().getIdentifier()); |
| 11394 |
getParser().getStreamer().emitThumbFunc(Func); |
11394 |
getParser().getStreamer().emitThumbFunc(Func); |
| 11395 |
Parser.Lex(); |
11395 |
Parser.Lex(); |
| 11396 |
if (parseEOL()) |
11396 |
if (parseEOL()) |
| 11397 |
return true; |
11397 |
return true; |
| 11398 |
return false; |
11398 |
return false; |
| 11399 |
} |
11399 |
} |
| 11400 |
} |
11400 |
} |
| 11401 |
|
11401 |
|
| 11402 |
if (parseEOL()) |
11402 |
if (parseEOL()) |
| 11403 |
return true; |
11403 |
return true; |
| 11404 |
|
11404 |
|
| 11405 |
// .thumb_func implies .thumb |
11405 |
// .thumb_func implies .thumb |
| 11406 |
if (!isThumb()) |
11406 |
if (!isThumb()) |
| 11407 |
SwitchMode(); |
11407 |
SwitchMode(); |
| 11408 |
|
11408 |
|
| 11409 |
getParser().getStreamer().emitAssemblerFlag(MCAF_Code16); |
11409 |
getParser().getStreamer().emitAssemblerFlag(MCAF_Code16); |
| 11410 |
|
11410 |
|
| 11411 |
NextSymbolIsThumb = true; |
11411 |
NextSymbolIsThumb = true; |
| 11412 |
return false; |
11412 |
return false; |
| 11413 |
} |
11413 |
} |
| 11414 |
|
11414 |
|
| 11415 |
/// parseDirectiveSyntax |
11415 |
/// parseDirectiveSyntax |
| 11416 |
/// ::= .syntax unified | divided |
11416 |
/// ::= .syntax unified | divided |
| 11417 |
bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) { |
11417 |
bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) { |
| 11418 |
MCAsmParser &Parser = getParser(); |
11418 |
MCAsmParser &Parser = getParser(); |
| 11419 |
const AsmToken &Tok = Parser.getTok(); |
11419 |
const AsmToken &Tok = Parser.getTok(); |
| 11420 |
if (Tok.isNot(AsmToken::Identifier)) { |
11420 |
if (Tok.isNot(AsmToken::Identifier)) { |
| 11421 |
Error(L, "unexpected token in .syntax directive"); |
11421 |
Error(L, "unexpected token in .syntax directive"); |
| 11422 |
return false; |
11422 |
return false; |
| 11423 |
} |
11423 |
} |
| 11424 |
|
11424 |
|
| 11425 |
StringRef Mode = Tok.getString(); |
11425 |
StringRef Mode = Tok.getString(); |
| 11426 |
Parser.Lex(); |
11426 |
Parser.Lex(); |
| 11427 |
if (check(Mode == "divided" || Mode == "DIVIDED", L, |
11427 |
if (check(Mode == "divided" || Mode == "DIVIDED", L, |
| 11428 |
"'.syntax divided' arm assembly not supported") || |
11428 |
"'.syntax divided' arm assembly not supported") || |
| 11429 |
check(Mode != "unified" && Mode != "UNIFIED", L, |
11429 |
check(Mode != "unified" && Mode != "UNIFIED", L, |
| 11430 |
"unrecognized syntax mode in .syntax directive") || |
11430 |
"unrecognized syntax mode in .syntax directive") || |
| 11431 |
parseEOL()) |
11431 |
parseEOL()) |
| 11432 |
return true; |
11432 |
return true; |
| 11433 |
|
11433 |
|
| 11434 |
// TODO tell the MC streamer the mode |
11434 |
// TODO tell the MC streamer the mode |
| 11435 |
// getParser().getStreamer().Emit???(); |
11435 |
// getParser().getStreamer().Emit???(); |
| 11436 |
return false; |
11436 |
return false; |
| 11437 |
} |
11437 |
} |
| 11438 |
|
11438 |
|
| 11439 |
/// parseDirectiveCode |
11439 |
/// parseDirectiveCode |
| 11440 |
/// ::= .code 16 | 32 |
11440 |
/// ::= .code 16 | 32 |
| 11441 |
bool ARMAsmParser::parseDirectiveCode(SMLoc L) { |
11441 |
bool ARMAsmParser::parseDirectiveCode(SMLoc L) { |
| 11442 |
MCAsmParser &Parser = getParser(); |
11442 |
MCAsmParser &Parser = getParser(); |
| 11443 |
const AsmToken &Tok = Parser.getTok(); |
11443 |
const AsmToken &Tok = Parser.getTok(); |
| 11444 |
if (Tok.isNot(AsmToken::Integer)) |
11444 |
if (Tok.isNot(AsmToken::Integer)) |
| 11445 |
return Error(L, "unexpected token in .code directive"); |
11445 |
return Error(L, "unexpected token in .code directive"); |
| 11446 |
int64_t Val = Parser.getTok().getIntVal(); |
11446 |
int64_t Val = Parser.getTok().getIntVal(); |
| 11447 |
if (Val != 16 && Val != 32) { |
11447 |
if (Val != 16 && Val != 32) { |
| 11448 |
Error(L, "invalid operand to .code directive"); |
11448 |
Error(L, "invalid operand to .code directive"); |
| 11449 |
return false; |
11449 |
return false; |
| 11450 |
} |
11450 |
} |
| 11451 |
Parser.Lex(); |
11451 |
Parser.Lex(); |
| 11452 |
|
11452 |
|
| 11453 |
if (parseEOL()) |
11453 |
if (parseEOL()) |
| 11454 |
return true; |
11454 |
return true; |
| 11455 |
|
11455 |
|
| 11456 |
if (Val == 16) { |
11456 |
if (Val == 16) { |
| 11457 |
if (!hasThumb()) |
11457 |
if (!hasThumb()) |
| 11458 |
return Error(L, "target does not support Thumb mode"); |
11458 |
return Error(L, "target does not support Thumb mode"); |
| 11459 |
|
11459 |
|
| 11460 |
if (!isThumb()) |
11460 |
if (!isThumb()) |
| 11461 |
SwitchMode(); |
11461 |
SwitchMode(); |
| 11462 |
getParser().getStreamer().emitAssemblerFlag(MCAF_Code16); |
11462 |
getParser().getStreamer().emitAssemblerFlag(MCAF_Code16); |
| 11463 |
} else { |
11463 |
} else { |
| 11464 |
if (!hasARM()) |
11464 |
if (!hasARM()) |
| 11465 |
return Error(L, "target does not support ARM mode"); |
11465 |
return Error(L, "target does not support ARM mode"); |
| 11466 |
|
11466 |
|
| 11467 |
if (isThumb()) |
11467 |
if (isThumb()) |
| 11468 |
SwitchMode(); |
11468 |
SwitchMode(); |
| 11469 |
getParser().getStreamer().emitAssemblerFlag(MCAF_Code32); |
11469 |
getParser().getStreamer().emitAssemblerFlag(MCAF_Code32); |
| 11470 |
} |
11470 |
} |
| 11471 |
|
11471 |
|
| 11472 |
return false; |
11472 |
return false; |
| 11473 |
} |
11473 |
} |
| 11474 |
|
11474 |
|
| 11475 |
/// parseDirectiveReq |
11475 |
/// parseDirectiveReq |
| 11476 |
/// ::= name .req registername |
11476 |
/// ::= name .req registername |
| 11477 |
bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { |
11477 |
bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { |
| 11478 |
MCAsmParser &Parser = getParser(); |
11478 |
MCAsmParser &Parser = getParser(); |
| 11479 |
Parser.Lex(); // Eat the '.req' token. |
11479 |
Parser.Lex(); // Eat the '.req' token. |
| 11480 |
MCRegister Reg; |
11480 |
MCRegister Reg; |
| 11481 |
SMLoc SRegLoc, ERegLoc; |
11481 |
SMLoc SRegLoc, ERegLoc; |
| 11482 |
if (check(parseRegister(Reg, SRegLoc, ERegLoc), SRegLoc, |
11482 |
if (check(parseRegister(Reg, SRegLoc, ERegLoc), SRegLoc, |
| 11483 |
"register name expected") || |
11483 |
"register name expected") || |
| 11484 |
parseEOL()) |
11484 |
parseEOL()) |
| 11485 |
return true; |
11485 |
return true; |
| 11486 |
|
11486 |
|
| 11487 |
if (RegisterReqs.insert(std::make_pair(Name, Reg)).first->second != Reg) |
11487 |
if (RegisterReqs.insert(std::make_pair(Name, Reg)).first->second != Reg) |
| 11488 |
return Error(SRegLoc, |
11488 |
return Error(SRegLoc, |
| 11489 |
"redefinition of '" + Name + "' does not match original."); |
11489 |
"redefinition of '" + Name + "' does not match original."); |
| 11490 |
|
11490 |
|
| 11491 |
return false; |
11491 |
return false; |
| 11492 |
} |
11492 |
} |
| 11493 |
|
11493 |
|
| 11494 |
/// parseDirectiveUneq |
11494 |
/// parseDirectiveUneq |
| 11495 |
/// ::= .unreq registername |
11495 |
/// ::= .unreq registername |
| 11496 |
bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) { |
11496 |
bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) { |
| 11497 |
MCAsmParser &Parser = getParser(); |
11497 |
MCAsmParser &Parser = getParser(); |
| 11498 |
if (Parser.getTok().isNot(AsmToken::Identifier)) |
11498 |
if (Parser.getTok().isNot(AsmToken::Identifier)) |
| 11499 |
return Error(L, "unexpected input in .unreq directive."); |
11499 |
return Error(L, "unexpected input in .unreq directive."); |
| 11500 |
RegisterReqs.erase(Parser.getTok().getIdentifier().lower()); |
11500 |
RegisterReqs.erase(Parser.getTok().getIdentifier().lower()); |
| 11501 |
Parser.Lex(); // Eat the identifier. |
11501 |
Parser.Lex(); // Eat the identifier. |
| 11502 |
return parseEOL(); |
11502 |
return parseEOL(); |
| 11503 |
} |
11503 |
} |
| 11504 |
|
11504 |
|
| 11505 |
// After changing arch/CPU, try to put the ARM/Thumb mode back to what it was |
11505 |
// After changing arch/CPU, try to put the ARM/Thumb mode back to what it was |
| 11506 |
// before, if supported by the new target, or emit mapping symbols for the mode |
11506 |
// before, if supported by the new target, or emit mapping symbols for the mode |
| 11507 |
// switch. |
11507 |
// switch. |
| 11508 |
void ARMAsmParser::FixModeAfterArchChange(bool WasThumb, SMLoc Loc) { |
11508 |
void ARMAsmParser::FixModeAfterArchChange(bool WasThumb, SMLoc Loc) { |
| 11509 |
if (WasThumb != isThumb()) { |
11509 |
if (WasThumb != isThumb()) { |
| 11510 |
if (WasThumb && hasThumb()) { |
11510 |
if (WasThumb && hasThumb()) { |
| 11511 |
// Stay in Thumb mode |
11511 |
// Stay in Thumb mode |
| 11512 |
SwitchMode(); |
11512 |
SwitchMode(); |
| 11513 |
} else if (!WasThumb && hasARM()) { |
11513 |
} else if (!WasThumb && hasARM()) { |
| 11514 |
// Stay in ARM mode |
11514 |
// Stay in ARM mode |
| 11515 |
SwitchMode(); |
11515 |
SwitchMode(); |
| 11516 |
} else { |
11516 |
} else { |
| 11517 |
// Mode switch forced, because the new arch doesn't support the old mode. |
11517 |
// Mode switch forced, because the new arch doesn't support the old mode. |
| 11518 |
getParser().getStreamer().emitAssemblerFlag(isThumb() ? MCAF_Code16 |
11518 |
getParser().getStreamer().emitAssemblerFlag(isThumb() ? MCAF_Code16 |
| 11519 |
: MCAF_Code32); |
11519 |
: MCAF_Code32); |
| 11520 |
// Warn about the implcit mode switch. GAS does not switch modes here, |
11520 |
// Warn about the implcit mode switch. GAS does not switch modes here, |
| 11521 |
// but instead stays in the old mode, reporting an error on any following |
11521 |
// but instead stays in the old mode, reporting an error on any following |
| 11522 |
// instructions as the mode does not exist on the target. |
11522 |
// instructions as the mode does not exist on the target. |
| 11523 |
Warning(Loc, Twine("new target does not support ") + |
11523 |
Warning(Loc, Twine("new target does not support ") + |
| 11524 |
(WasThumb ? "thumb" : "arm") + " mode, switching to " + |
11524 |
(WasThumb ? "thumb" : "arm") + " mode, switching to " + |
| 11525 |
(!WasThumb ? "thumb" : "arm") + " mode"); |
11525 |
(!WasThumb ? "thumb" : "arm") + " mode"); |
| 11526 |
} |
11526 |
} |
| 11527 |
} |
11527 |
} |
| 11528 |
} |
11528 |
} |
| 11529 |
|
11529 |
|
| 11530 |
/// parseDirectiveArch |
11530 |
/// parseDirectiveArch |
| 11531 |
/// ::= .arch token |
11531 |
/// ::= .arch token |
| 11532 |
bool ARMAsmParser::parseDirectiveArch(SMLoc L) { |
11532 |
bool ARMAsmParser::parseDirectiveArch(SMLoc L) { |
| 11533 |
StringRef Arch = getParser().parseStringToEndOfStatement().trim(); |
11533 |
StringRef Arch = getParser().parseStringToEndOfStatement().trim(); |
| 11534 |
ARM::ArchKind ID = ARM::parseArch(Arch); |
11534 |
ARM::ArchKind ID = ARM::parseArch(Arch); |
| 11535 |
|
11535 |
|
| 11536 |
if (ID == ARM::ArchKind::INVALID) |
11536 |
if (ID == ARM::ArchKind::INVALID) |
| 11537 |
return Error(L, "Unknown arch name"); |
11537 |
return Error(L, "Unknown arch name"); |
| 11538 |
|
11538 |
|
| 11539 |
bool WasThumb = isThumb(); |
11539 |
bool WasThumb = isThumb(); |
| 11540 |
Triple T; |
11540 |
Triple T; |
| 11541 |
MCSubtargetInfo &STI = copySTI(); |
11541 |
MCSubtargetInfo &STI = copySTI(); |
| 11542 |
STI.setDefaultFeatures("", /*TuneCPU*/ "", |
11542 |
STI.setDefaultFeatures("", /*TuneCPU*/ "", |
| 11543 |
("+" + ARM::getArchName(ID)).str()); |
11543 |
("+" + ARM::getArchName(ID)).str()); |
| 11544 |
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); |
11544 |
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); |
| 11545 |
FixModeAfterArchChange(WasThumb, L); |
11545 |
FixModeAfterArchChange(WasThumb, L); |
| 11546 |
|
11546 |
|
| 11547 |
getTargetStreamer().emitArch(ID); |
11547 |
getTargetStreamer().emitArch(ID); |
| 11548 |
return false; |
11548 |
return false; |
| 11549 |
} |
11549 |
} |
| 11550 |
|
11550 |
|
| 11551 |
/// parseDirectiveEabiAttr |
11551 |
/// parseDirectiveEabiAttr |
| 11552 |
/// ::= .eabi_attribute int, int [, "str"] |
11552 |
/// ::= .eabi_attribute int, int [, "str"] |
| 11553 |
/// ::= .eabi_attribute Tag_name, int [, "str"] |
11553 |
/// ::= .eabi_attribute Tag_name, int [, "str"] |
| 11554 |
bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { |
11554 |
bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { |
| 11555 |
MCAsmParser &Parser = getParser(); |
11555 |
MCAsmParser &Parser = getParser(); |
| 11556 |
int64_t Tag; |
11556 |
int64_t Tag; |
| 11557 |
SMLoc TagLoc; |
11557 |
SMLoc TagLoc; |
| 11558 |
TagLoc = Parser.getTok().getLoc(); |
11558 |
TagLoc = Parser.getTok().getLoc(); |
| 11559 |
if (Parser.getTok().is(AsmToken::Identifier)) { |
11559 |
if (Parser.getTok().is(AsmToken::Identifier)) { |
| 11560 |
StringRef Name = Parser.getTok().getIdentifier(); |
11560 |
StringRef Name = Parser.getTok().getIdentifier(); |
| 11561 |
std::optional Ret = ELFAttrs::attrTypeFromString( |
11561 |
std::optional Ret = ELFAttrs::attrTypeFromString( |
| 11562 |
Name, ARMBuildAttrs::getARMAttributeTags()); |
11562 |
Name, ARMBuildAttrs::getARMAttributeTags()); |
| 11563 |
if (!Ret) { |
11563 |
if (!Ret) { |
| 11564 |
Error(TagLoc, "attribute name not recognised: " + Name); |
11564 |
Error(TagLoc, "attribute name not recognised: " + Name); |
| 11565 |
return false; |
11565 |
return false; |
| 11566 |
} |
11566 |
} |
| 11567 |
Tag = *Ret; |
11567 |
Tag = *Ret; |
| 11568 |
Parser.Lex(); |
11568 |
Parser.Lex(); |
| 11569 |
} else { |
11569 |
} else { |
| 11570 |
const MCExpr *AttrExpr; |
11570 |
const MCExpr *AttrExpr; |
| 11571 |
|
11571 |
|
| 11572 |
TagLoc = Parser.getTok().getLoc(); |
11572 |
TagLoc = Parser.getTok().getLoc(); |
| 11573 |
if (Parser.parseExpression(AttrExpr)) |
11573 |
if (Parser.parseExpression(AttrExpr)) |
| 11574 |
return true; |
11574 |
return true; |
| 11575 |
|
11575 |
|
| 11576 |
const MCConstantExpr *CE = dyn_cast(AttrExpr); |
11576 |
const MCConstantExpr *CE = dyn_cast(AttrExpr); |
| 11577 |
if (check(!CE, TagLoc, "expected numeric constant")) |
11577 |
if (check(!CE, TagLoc, "expected numeric constant")) |
| 11578 |
return true; |
11578 |
return true; |
| 11579 |
|
11579 |
|
| 11580 |
Tag = CE->getValue(); |
11580 |
Tag = CE->getValue(); |
| 11581 |
} |
11581 |
} |
| 11582 |
|
11582 |
|
| 11583 |
if (Parser.parseComma()) |
11583 |
if (Parser.parseComma()) |
| 11584 |
return true; |
11584 |
return true; |
| 11585 |
|
11585 |
|
| 11586 |
StringRef StringValue = ""; |
11586 |
StringRef StringValue = ""; |
| 11587 |
bool IsStringValue = false; |
11587 |
bool IsStringValue = false; |
| 11588 |
|
11588 |
|
| 11589 |
int64_t IntegerValue = 0; |
11589 |
int64_t IntegerValue = 0; |
| 11590 |
bool IsIntegerValue = false; |
11590 |
bool IsIntegerValue = false; |
| 11591 |
|
11591 |
|
| 11592 |
if (Tag == ARMBuildAttrs::CPU_raw_name || Tag == ARMBuildAttrs::CPU_name) |
11592 |
if (Tag == ARMBuildAttrs::CPU_raw_name || Tag == ARMBuildAttrs::CPU_name) |
| 11593 |
IsStringValue = true; |
11593 |
IsStringValue = true; |
| 11594 |
else if (Tag == ARMBuildAttrs::compatibility) { |
11594 |
else if (Tag == ARMBuildAttrs::compatibility) { |
| 11595 |
IsStringValue = true; |
11595 |
IsStringValue = true; |
| 11596 |
IsIntegerValue = true; |
11596 |
IsIntegerValue = true; |
| 11597 |
} else if (Tag < 32 || Tag % 2 == 0) |
11597 |
} else if (Tag < 32 || Tag % 2 == 0) |
| 11598 |
IsIntegerValue = true; |
11598 |
IsIntegerValue = true; |
| 11599 |
else if (Tag % 2 == 1) |
11599 |
else if (Tag % 2 == 1) |
| 11600 |
IsStringValue = true; |
11600 |
IsStringValue = true; |
| 11601 |
else |
11601 |
else |
| 11602 |
llvm_unreachable("invalid tag type"); |
11602 |
llvm_unreachable("invalid tag type"); |
| 11603 |
|
11603 |
|
| 11604 |
if (IsIntegerValue) { |
11604 |
if (IsIntegerValue) { |
| 11605 |
const MCExpr *ValueExpr; |
11605 |
const MCExpr *ValueExpr; |
| 11606 |
SMLoc ValueExprLoc = Parser.getTok().getLoc(); |
11606 |
SMLoc ValueExprLoc = Parser.getTok().getLoc(); |
| 11607 |
if (Parser.parseExpression(ValueExpr)) |
11607 |
if (Parser.parseExpression(ValueExpr)) |
| 11608 |
return true; |
11608 |
return true; |
| 11609 |
|
11609 |
|
| 11610 |
const MCConstantExpr *CE = dyn_cast(ValueExpr); |
11610 |
const MCConstantExpr *CE = dyn_cast(ValueExpr); |
| 11611 |
if (!CE) |
11611 |
if (!CE) |
| 11612 |
return Error(ValueExprLoc, "expected numeric constant"); |
11612 |
return Error(ValueExprLoc, "expected numeric constant"); |
| 11613 |
IntegerValue = CE->getValue(); |
11613 |
IntegerValue = CE->getValue(); |
| 11614 |
} |
11614 |
} |
| 11615 |
|
11615 |
|
| 11616 |
if (Tag == ARMBuildAttrs::compatibility) { |
11616 |
if (Tag == ARMBuildAttrs::compatibility) { |
| 11617 |
if (Parser.parseComma()) |
11617 |
if (Parser.parseComma()) |
| 11618 |
return true; |
11618 |
return true; |
| 11619 |
} |
11619 |
} |
| 11620 |
|
11620 |
|
| 11621 |
std::string EscapedValue; |
11621 |
std::string EscapedValue; |
| 11622 |
if (IsStringValue) { |
11622 |
if (IsStringValue) { |
| 11623 |
if (Parser.getTok().isNot(AsmToken::String)) |
11623 |
if (Parser.getTok().isNot(AsmToken::String)) |
| 11624 |
return Error(Parser.getTok().getLoc(), "bad string constant"); |
11624 |
return Error(Parser.getTok().getLoc(), "bad string constant"); |
| 11625 |
|
11625 |
|
| 11626 |
if (Tag == ARMBuildAttrs::also_compatible_with) { |
11626 |
if (Tag == ARMBuildAttrs::also_compatible_with) { |
| 11627 |
if (Parser.parseEscapedString(EscapedValue)) |
11627 |
if (Parser.parseEscapedString(EscapedValue)) |
| 11628 |
return Error(Parser.getTok().getLoc(), "bad escaped string constant"); |
11628 |
return Error(Parser.getTok().getLoc(), "bad escaped string constant"); |
| 11629 |
|
11629 |
|
| 11630 |
StringValue = EscapedValue; |
11630 |
StringValue = EscapedValue; |
| 11631 |
} else { |
11631 |
} else { |
| 11632 |
StringValue = Parser.getTok().getStringContents(); |
11632 |
StringValue = Parser.getTok().getStringContents(); |
| 11633 |
Parser.Lex(); |
11633 |
Parser.Lex(); |
| 11634 |
} |
11634 |
} |
| 11635 |
} |
11635 |
} |
| 11636 |
|
11636 |
|
| 11637 |
if (Parser.parseEOL()) |
11637 |
if (Parser.parseEOL()) |
| 11638 |
return true; |
11638 |
return true; |
| 11639 |
|
11639 |
|
| 11640 |
if (IsIntegerValue && IsStringValue) { |
11640 |
if (IsIntegerValue && IsStringValue) { |
| 11641 |
assert(Tag == ARMBuildAttrs::compatibility); |
11641 |
assert(Tag == ARMBuildAttrs::compatibility); |
| 11642 |
getTargetStreamer().emitIntTextAttribute(Tag, IntegerValue, StringValue); |
11642 |
getTargetStreamer().emitIntTextAttribute(Tag, IntegerValue, StringValue); |
| 11643 |
} else if (IsIntegerValue) |
11643 |
} else if (IsIntegerValue) |
| 11644 |
getTargetStreamer().emitAttribute(Tag, IntegerValue); |
11644 |
getTargetStreamer().emitAttribute(Tag, IntegerValue); |
| 11645 |
else if (IsStringValue) |
11645 |
else if (IsStringValue) |
| 11646 |
getTargetStreamer().emitTextAttribute(Tag, StringValue); |
11646 |
getTargetStreamer().emitTextAttribute(Tag, StringValue); |
| 11647 |
return false; |
11647 |
return false; |
| 11648 |
} |
11648 |
} |
| 11649 |
|
11649 |
|
| 11650 |
/// parseDirectiveCPU |
11650 |
/// parseDirectiveCPU |
| 11651 |
/// ::= .cpu str |
11651 |
/// ::= .cpu str |
| 11652 |
bool ARMAsmParser::parseDirectiveCPU(SMLoc L) { |
11652 |
bool ARMAsmParser::parseDirectiveCPU(SMLoc L) { |
| 11653 |
StringRef CPU = getParser().parseStringToEndOfStatement().trim(); |
11653 |
StringRef CPU = getParser().parseStringToEndOfStatement().trim(); |
| 11654 |
getTargetStreamer().emitTextAttribute(ARMBuildAttrs::CPU_name, CPU); |
11654 |
getTargetStreamer().emitTextAttribute(ARMBuildAttrs::CPU_name, CPU); |
| 11655 |
|
11655 |
|
| 11656 |
// FIXME: This is using table-gen data, but should be moved to |
11656 |
// FIXME: This is using table-gen data, but should be moved to |
| 11657 |
// ARMTargetParser once that is table-gen'd. |
11657 |
// ARMTargetParser once that is table-gen'd. |
| 11658 |
if (!getSTI().isCPUStringValid(CPU)) |
11658 |
if (!getSTI().isCPUStringValid(CPU)) |
| 11659 |
return Error(L, "Unknown CPU name"); |
11659 |
return Error(L, "Unknown CPU name"); |
| 11660 |
|
11660 |
|
| 11661 |
bool WasThumb = isThumb(); |
11661 |
bool WasThumb = isThumb(); |
| 11662 |
MCSubtargetInfo &STI = copySTI(); |
11662 |
MCSubtargetInfo &STI = copySTI(); |
| 11663 |
STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, ""); |
11663 |
STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, ""); |
| 11664 |
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); |
11664 |
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); |
| 11665 |
FixModeAfterArchChange(WasThumb, L); |
11665 |
FixModeAfterArchChange(WasThumb, L); |
| 11666 |
|
11666 |
|
| 11667 |
return false; |
11667 |
return false; |
| 11668 |
} |
11668 |
} |
| 11669 |
|
11669 |
|
| 11670 |
/// parseDirectiveFPU |
11670 |
/// parseDirectiveFPU |
| 11671 |
/// ::= .fpu str |
11671 |
/// ::= .fpu str |
| 11672 |
bool ARMAsmParser::parseDirectiveFPU(SMLoc L) { |
11672 |
bool ARMAsmParser::parseDirectiveFPU(SMLoc L) { |
| 11673 |
SMLoc FPUNameLoc = getTok().getLoc(); |
11673 |
SMLoc FPUNameLoc = getTok().getLoc(); |
| 11674 |
StringRef FPU = getParser().parseStringToEndOfStatement().trim(); |
11674 |
StringRef FPU = getParser().parseStringToEndOfStatement().trim(); |
| 11675 |
|
11675 |
|
| 11676 |
ARM::FPUKind ID = ARM::parseFPU(FPU); |
11676 |
ARM::FPUKind ID = ARM::parseFPU(FPU); |
| 11677 |
std::vector Features; |
11677 |
std::vector Features; |
| 11678 |
if (!ARM::getFPUFeatures(ID, Features)) |
11678 |
if (!ARM::getFPUFeatures(ID, Features)) |
| 11679 |
return Error(FPUNameLoc, "Unknown FPU name"); |
11679 |
return Error(FPUNameLoc, "Unknown FPU name"); |
| 11680 |
|
11680 |
|
| 11681 |
MCSubtargetInfo &STI = copySTI(); |
11681 |
MCSubtargetInfo &STI = copySTI(); |
| 11682 |
for (auto Feature : Features) |
11682 |
for (auto Feature : Features) |
| 11683 |
STI.ApplyFeatureFlag(Feature); |
11683 |
STI.ApplyFeatureFlag(Feature); |
| 11684 |
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); |
11684 |
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); |
| 11685 |
|
11685 |
|
| 11686 |
getTargetStreamer().emitFPU(ID); |
11686 |
getTargetStreamer().emitFPU(ID); |
| 11687 |
return false; |
11687 |
return false; |
| 11688 |
} |
11688 |
} |
| 11689 |
|
11689 |
|
| 11690 |
/// parseDirectiveFnStart |
11690 |
/// parseDirectiveFnStart |
| 11691 |
/// ::= .fnstart |
11691 |
/// ::= .fnstart |
| 11692 |
bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) { |
11692 |
bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) { |
| 11693 |
if (parseEOL()) |
11693 |
if (parseEOL()) |
| 11694 |
return true; |
11694 |
return true; |
| 11695 |
|
11695 |
|
| 11696 |
if (UC.hasFnStart()) { |
11696 |
if (UC.hasFnStart()) { |
| 11697 |
Error(L, ".fnstart starts before the end of previous one"); |
11697 |
Error(L, ".fnstart starts before the end of previous one"); |
| 11698 |
UC.emitFnStartLocNotes(); |
11698 |
UC.emitFnStartLocNotes(); |
| 11699 |
return true; |
11699 |
return true; |
| 11700 |
} |
11700 |
} |
| 11701 |
|
11701 |
|
| 11702 |
// Reset the unwind directives parser state |
11702 |
// Reset the unwind directives parser state |
| 11703 |
UC.reset(); |
11703 |
UC.reset(); |
| 11704 |
|
11704 |
|
| 11705 |
getTargetStreamer().emitFnStart(); |
11705 |
getTargetStreamer().emitFnStart(); |
| 11706 |
|
11706 |
|
| 11707 |
UC.recordFnStart(L); |
11707 |
UC.recordFnStart(L); |
| 11708 |
return false; |
11708 |
return false; |
| 11709 |
} |
11709 |
} |
| 11710 |
|
11710 |
|
| 11711 |
/// parseDirectiveFnEnd |
11711 |
/// parseDirectiveFnEnd |
| 11712 |
/// ::= .fnend |
11712 |
/// ::= .fnend |
| 11713 |
bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) { |
11713 |
bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) { |
| 11714 |
if (parseEOL()) |
11714 |
if (parseEOL()) |
| 11715 |
return true; |
11715 |
return true; |
| 11716 |
// Check the ordering of unwind directives |
11716 |
// Check the ordering of unwind directives |
| 11717 |
if (!UC.hasFnStart()) |
11717 |
if (!UC.hasFnStart()) |
| 11718 |
return Error(L, ".fnstart must precede .fnend directive"); |
11718 |
return Error(L, ".fnstart must precede .fnend directive"); |
| 11719 |
|
11719 |
|
| 11720 |
// Reset the unwind directives parser state |
11720 |
// Reset the unwind directives parser state |
| 11721 |
getTargetStreamer().emitFnEnd(); |
11721 |
getTargetStreamer().emitFnEnd(); |
| 11722 |
|
11722 |
|
| 11723 |
UC.reset(); |
11723 |
UC.reset(); |
| 11724 |
return false; |
11724 |
return false; |
| 11725 |
} |
11725 |
} |
| 11726 |
|
11726 |
|
| 11727 |
/// parseDirectiveCantUnwind |
11727 |
/// parseDirectiveCantUnwind |
| 11728 |
/// ::= .cantunwind |
11728 |
/// ::= .cantunwind |
| 11729 |
bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) { |
11729 |
bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) { |
| 11730 |
if (parseEOL()) |
11730 |
if (parseEOL()) |
| 11731 |
return true; |
11731 |
return true; |
| 11732 |
|
11732 |
|
| 11733 |
UC.recordCantUnwind(L); |
11733 |
UC.recordCantUnwind(L); |
| 11734 |
// Check the ordering of unwind directives |
11734 |
// Check the ordering of unwind directives |
| 11735 |
if (check(!UC.hasFnStart(), L, ".fnstart must precede .cantunwind directive")) |
11735 |
if (check(!UC.hasFnStart(), L, ".fnstart must precede .cantunwind directive")) |
| 11736 |
return true; |
11736 |
return true; |
| 11737 |
|
11737 |
|
| 11738 |
if (UC.hasHandlerData()) { |
11738 |
if (UC.hasHandlerData()) { |
| 11739 |
Error(L, ".cantunwind can't be used with .handlerdata directive"); |
11739 |
Error(L, ".cantunwind can't be used with .handlerdata directive"); |
| 11740 |
UC.emitHandlerDataLocNotes(); |
11740 |
UC.emitHandlerDataLocNotes(); |
| 11741 |
return true; |
11741 |
return true; |
| 11742 |
} |
11742 |
} |
| 11743 |
if (UC.hasPersonality()) { |
11743 |
if (UC.hasPersonality()) { |
| 11744 |
Error(L, ".cantunwind can't be used with .personality directive"); |
11744 |
Error(L, ".cantunwind can't be used with .personality directive"); |
| 11745 |
UC.emitPersonalityLocNotes(); |
11745 |
UC.emitPersonalityLocNotes(); |
| 11746 |
return true; |
11746 |
return true; |
| 11747 |
} |
11747 |
} |
| 11748 |
|
11748 |
|
| 11749 |
getTargetStreamer().emitCantUnwind(); |
11749 |
getTargetStreamer().emitCantUnwind(); |
| 11750 |
return false; |
11750 |
return false; |
| 11751 |
} |
11751 |
} |
| 11752 |
|
11752 |
|
| 11753 |
/// parseDirectivePersonality |
11753 |
/// parseDirectivePersonality |
| 11754 |
/// ::= .personality name |
11754 |
/// ::= .personality name |
| 11755 |
bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { |
11755 |
bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { |
| 11756 |
MCAsmParser &Parser = getParser(); |
11756 |
MCAsmParser &Parser = getParser(); |
| 11757 |
bool HasExistingPersonality = UC.hasPersonality(); |
11757 |
bool HasExistingPersonality = UC.hasPersonality(); |
| 11758 |
|
11758 |
|
| 11759 |
// Parse the name of the personality routine |
11759 |
// Parse the name of the personality routine |
| 11760 |
if (Parser.getTok().isNot(AsmToken::Identifier)) |
11760 |
if (Parser.getTok().isNot(AsmToken::Identifier)) |
| 11761 |
return Error(L, "unexpected input in .personality directive."); |
11761 |
return Error(L, "unexpected input in .personality directive."); |
| 11762 |
StringRef Name(Parser.getTok().getIdentifier()); |
11762 |
StringRef Name(Parser.getTok().getIdentifier()); |
| 11763 |
Parser.Lex(); |
11763 |
Parser.Lex(); |
| 11764 |
|
11764 |
|
| 11765 |
if (parseEOL()) |
11765 |
if (parseEOL()) |
| 11766 |
return true; |
11766 |
return true; |
| 11767 |
|
11767 |
|
| 11768 |
UC.recordPersonality(L); |
11768 |
UC.recordPersonality(L); |
| 11769 |
|
11769 |
|
| 11770 |
// Check the ordering of unwind directives |
11770 |
// Check the ordering of unwind directives |
| 11771 |
if (!UC.hasFnStart()) |
11771 |
if (!UC.hasFnStart()) |
| 11772 |
return Error(L, ".fnstart must precede .personality directive"); |
11772 |
return Error(L, ".fnstart must precede .personality directive"); |
| 11773 |
if (UC.cantUnwind()) { |
11773 |
if (UC.cantUnwind()) { |
| 11774 |
Error(L, ".personality can't be used with .cantunwind directive"); |
11774 |
Error(L, ".personality can't be used with .cantunwind directive"); |
| 11775 |
UC.emitCantUnwindLocNotes(); |
11775 |
UC.emitCantUnwindLocNotes(); |
| 11776 |
return true; |
11776 |
return true; |
| 11777 |
} |
11777 |
} |
| 11778 |
if (UC.hasHandlerData()) { |
11778 |
if (UC.hasHandlerData()) { |
| 11779 |
Error(L, ".personality must precede .handlerdata directive"); |
11779 |
Error(L, ".personality must precede .handlerdata directive"); |
| 11780 |
UC.emitHandlerDataLocNotes(); |
11780 |
UC.emitHandlerDataLocNotes(); |
| 11781 |
return true; |
11781 |
return true; |
| 11782 |
} |
11782 |
} |
| 11783 |
if (HasExistingPersonality) { |
11783 |
if (HasExistingPersonality) { |
| 11784 |
Error(L, "multiple personality directives"); |
11784 |
Error(L, "multiple personality directives"); |
| 11785 |
UC.emitPersonalityLocNotes(); |
11785 |
UC.emitPersonalityLocNotes(); |
| 11786 |
return true; |
11786 |
return true; |
| 11787 |
} |
11787 |
} |
| 11788 |
|
11788 |
|
| 11789 |
MCSymbol *PR = getParser().getContext().getOrCreateSymbol(Name); |
11789 |
MCSymbol *PR = getParser().getContext().getOrCreateSymbol(Name); |
| 11790 |
getTargetStreamer().emitPersonality(PR); |
11790 |
getTargetStreamer().emitPersonality(PR); |
| 11791 |
return false; |
11791 |
return false; |
| 11792 |
} |
11792 |
} |
| 11793 |
|
11793 |
|
| 11794 |
/// parseDirectiveHandlerData |
11794 |
/// parseDirectiveHandlerData |
| 11795 |
/// ::= .handlerdata |
11795 |
/// ::= .handlerdata |
| 11796 |
bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) { |
11796 |
bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) { |
| 11797 |
if (parseEOL()) |
11797 |
if (parseEOL()) |
| 11798 |
return true; |
11798 |
return true; |
| 11799 |
|
11799 |
|
| 11800 |
UC.recordHandlerData(L); |
11800 |
UC.recordHandlerData(L); |
| 11801 |
// Check the ordering of unwind directives |
11801 |
// Check the ordering of unwind directives |
| 11802 |
if (!UC.hasFnStart()) |
11802 |
if (!UC.hasFnStart()) |
| 11803 |
return Error(L, ".fnstart must precede .personality directive"); |
11803 |
return Error(L, ".fnstart must precede .personality directive"); |
| 11804 |
if (UC.cantUnwind()) { |
11804 |
if (UC.cantUnwind()) { |
| 11805 |
Error(L, ".handlerdata can't be used with .cantunwind directive"); |
11805 |
Error(L, ".handlerdata can't be used with .cantunwind directive"); |
| 11806 |
UC.emitCantUnwindLocNotes(); |
11806 |
UC.emitCantUnwindLocNotes(); |
| 11807 |
return true; |
11807 |
return true; |
| 11808 |
} |
11808 |
} |
| 11809 |
|
11809 |
|
| 11810 |
getTargetStreamer().emitHandlerData(); |
11810 |
getTargetStreamer().emitHandlerData(); |
| 11811 |
return false; |
11811 |
return false; |
| 11812 |
} |
11812 |
} |
| 11813 |
|
11813 |
|
| 11814 |
/// parseDirectiveSetFP |
11814 |
/// parseDirectiveSetFP |
| 11815 |
/// ::= .setfp fpreg, spreg [, offset] |
11815 |
/// ::= .setfp fpreg, spreg [, offset] |
| 11816 |
bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { |
11816 |
bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { |
| 11817 |
MCAsmParser &Parser = getParser(); |
11817 |
MCAsmParser &Parser = getParser(); |
| 11818 |
// Check the ordering of unwind directives |
11818 |
// Check the ordering of unwind directives |
| 11819 |
if (check(!UC.hasFnStart(), L, ".fnstart must precede .setfp directive") || |
11819 |
if (check(!UC.hasFnStart(), L, ".fnstart must precede .setfp directive") || |
| 11820 |
check(UC.hasHandlerData(), L, |
11820 |
check(UC.hasHandlerData(), L, |
| 11821 |
".setfp must precede .handlerdata directive")) |
11821 |
".setfp must precede .handlerdata directive")) |
| 11822 |
return true; |
11822 |
return true; |
| 11823 |
|
11823 |
|
| 11824 |
// Parse fpreg |
11824 |
// Parse fpreg |
| 11825 |
SMLoc FPRegLoc = Parser.getTok().getLoc(); |
11825 |
SMLoc FPRegLoc = Parser.getTok().getLoc(); |
| 11826 |
int FPReg = tryParseRegister(); |
11826 |
int FPReg = tryParseRegister(); |
| 11827 |
|
11827 |
|
| 11828 |
if (check(FPReg == -1, FPRegLoc, "frame pointer register expected") || |
11828 |
if (check(FPReg == -1, FPRegLoc, "frame pointer register expected") || |
| 11829 |
Parser.parseComma()) |
11829 |
Parser.parseComma()) |
| 11830 |
return true; |
11830 |
return true; |
| 11831 |
|
11831 |
|
| 11832 |
// Parse spreg |
11832 |
// Parse spreg |
| 11833 |
SMLoc SPRegLoc = Parser.getTok().getLoc(); |
11833 |
SMLoc SPRegLoc = Parser.getTok().getLoc(); |
| 11834 |
int SPReg = tryParseRegister(); |
11834 |
int SPReg = tryParseRegister(); |
| 11835 |
if (check(SPReg == -1, SPRegLoc, "stack pointer register expected") || |
11835 |
if (check(SPReg == -1, SPRegLoc, "stack pointer register expected") || |
| 11836 |
check(SPReg != ARM::SP && SPReg != UC.getFPReg(), SPRegLoc, |
11836 |
check(SPReg != ARM::SP && SPReg != UC.getFPReg(), SPRegLoc, |
| 11837 |
"register should be either $sp or the latest fp register")) |
11837 |
"register should be either $sp or the latest fp register")) |
| 11838 |
return true; |
11838 |
return true; |
| 11839 |
|
11839 |
|
| 11840 |
// Update the frame pointer register |
11840 |
// Update the frame pointer register |
| 11841 |
UC.saveFPReg(FPReg); |
11841 |
UC.saveFPReg(FPReg); |
| 11842 |
|
11842 |
|
| 11843 |
// Parse offset |
11843 |
// Parse offset |
| 11844 |
int64_t Offset = 0; |
11844 |
int64_t Offset = 0; |
| 11845 |
if (Parser.parseOptionalToken(AsmToken::Comma)) { |
11845 |
if (Parser.parseOptionalToken(AsmToken::Comma)) { |
| 11846 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
11846 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
| 11847 |
Parser.getTok().isNot(AsmToken::Dollar)) |
11847 |
Parser.getTok().isNot(AsmToken::Dollar)) |
| 11848 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
11848 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
| 11849 |
Parser.Lex(); // skip hash token. |
11849 |
Parser.Lex(); // skip hash token. |
| 11850 |
|
11850 |
|
| 11851 |
const MCExpr *OffsetExpr; |
11851 |
const MCExpr *OffsetExpr; |
| 11852 |
SMLoc ExLoc = Parser.getTok().getLoc(); |
11852 |
SMLoc ExLoc = Parser.getTok().getLoc(); |
| 11853 |
SMLoc EndLoc; |
11853 |
SMLoc EndLoc; |
| 11854 |
if (getParser().parseExpression(OffsetExpr, EndLoc)) |
11854 |
if (getParser().parseExpression(OffsetExpr, EndLoc)) |
| 11855 |
return Error(ExLoc, "malformed setfp offset"); |
11855 |
return Error(ExLoc, "malformed setfp offset"); |
| 11856 |
const MCConstantExpr *CE = dyn_cast(OffsetExpr); |
11856 |
const MCConstantExpr *CE = dyn_cast(OffsetExpr); |
| 11857 |
if (check(!CE, ExLoc, "setfp offset must be an immediate")) |
11857 |
if (check(!CE, ExLoc, "setfp offset must be an immediate")) |
| 11858 |
return true; |
11858 |
return true; |
| 11859 |
Offset = CE->getValue(); |
11859 |
Offset = CE->getValue(); |
| 11860 |
} |
11860 |
} |
| 11861 |
|
11861 |
|
| 11862 |
if (Parser.parseEOL()) |
11862 |
if (Parser.parseEOL()) |
| 11863 |
return true; |
11863 |
return true; |
| 11864 |
|
11864 |
|
| 11865 |
getTargetStreamer().emitSetFP(static_cast(FPReg), |
11865 |
getTargetStreamer().emitSetFP(static_cast(FPReg), |
| 11866 |
static_cast(SPReg), Offset); |
11866 |
static_cast(SPReg), Offset); |
| 11867 |
return false; |
11867 |
return false; |
| 11868 |
} |
11868 |
} |
| 11869 |
|
11869 |
|
| 11870 |
/// parseDirective |
11870 |
/// parseDirective |
| 11871 |
/// ::= .pad offset |
11871 |
/// ::= .pad offset |
| 11872 |
bool ARMAsmParser::parseDirectivePad(SMLoc L) { |
11872 |
bool ARMAsmParser::parseDirectivePad(SMLoc L) { |
| 11873 |
MCAsmParser &Parser = getParser(); |
11873 |
MCAsmParser &Parser = getParser(); |
| 11874 |
// Check the ordering of unwind directives |
11874 |
// Check the ordering of unwind directives |
| 11875 |
if (!UC.hasFnStart()) |
11875 |
if (!UC.hasFnStart()) |
| 11876 |
return Error(L, ".fnstart must precede .pad directive"); |
11876 |
return Error(L, ".fnstart must precede .pad directive"); |
| 11877 |
if (UC.hasHandlerData()) |
11877 |
if (UC.hasHandlerData()) |
| 11878 |
return Error(L, ".pad must precede .handlerdata directive"); |
11878 |
return Error(L, ".pad must precede .handlerdata directive"); |
| 11879 |
|
11879 |
|
| 11880 |
// Parse the offset |
11880 |
// Parse the offset |
| 11881 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
11881 |
if (Parser.getTok().isNot(AsmToken::Hash) && |
| 11882 |
Parser.getTok().isNot(AsmToken::Dollar)) |
11882 |
Parser.getTok().isNot(AsmToken::Dollar)) |
| 11883 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
11883 |
return Error(Parser.getTok().getLoc(), "'#' expected"); |
| 11884 |
Parser.Lex(); // skip hash token. |
11884 |
Parser.Lex(); // skip hash token. |
| 11885 |
|
11885 |
|
| 11886 |
const MCExpr *OffsetExpr; |
11886 |
const MCExpr *OffsetExpr; |
| 11887 |
SMLoc ExLoc = Parser.getTok().getLoc(); |
11887 |
SMLoc ExLoc = Parser.getTok().getLoc(); |
| 11888 |
SMLoc EndLoc; |
11888 |
SMLoc EndLoc; |
| 11889 |
if (getParser().parseExpression(OffsetExpr, EndLoc)) |
11889 |
if (getParser().parseExpression(OffsetExpr, EndLoc)) |
| 11890 |
return Error(ExLoc, "malformed pad offset"); |
11890 |
return Error(ExLoc, "malformed pad offset"); |
| 11891 |
const MCConstantExpr *CE = dyn_cast(OffsetExpr); |
11891 |
const MCConstantExpr *CE = dyn_cast(OffsetExpr); |
| 11892 |
if (!CE) |
11892 |
if (!CE) |
| 11893 |
return Error(ExLoc, "pad offset must be an immediate"); |
11893 |
return Error(ExLoc, "pad offset must be an immediate"); |
| 11894 |
|
11894 |
|
| 11895 |
if (parseEOL()) |
11895 |
if (parseEOL()) |
| 11896 |
return true; |
11896 |
return true; |
| 11897 |
|
11897 |
|
| 11898 |
getTargetStreamer().emitPad(CE->getValue()); |
11898 |
getTargetStreamer().emitPad(CE->getValue()); |
| 11899 |
return false; |
11899 |
return false; |
| 11900 |
} |
11900 |
} |
| 11901 |
|
11901 |
|
| 11902 |
/// parseDirectiveRegSave |
11902 |
/// parseDirectiveRegSave |
| 11903 |
/// ::= .save { registers } |
11903 |
/// ::= .save { registers } |
| 11904 |
/// ::= .vsave { registers } |
11904 |
/// ::= .vsave { registers } |
| 11905 |
bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { |
11905 |
bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { |
| 11906 |
// Check the ordering of unwind directives |
11906 |
// Check the ordering of unwind directives |
| 11907 |
if (!UC.hasFnStart()) |
11907 |
if (!UC.hasFnStart()) |
| 11908 |
return Error(L, ".fnstart must precede .save or .vsave directives"); |
11908 |
return Error(L, ".fnstart must precede .save or .vsave directives"); |
| 11909 |
if (UC.hasHandlerData()) |
11909 |
if (UC.hasHandlerData()) |
| 11910 |
return Error(L, ".save or .vsave must precede .handlerdata directive"); |
11910 |
return Error(L, ".save or .vsave must precede .handlerdata directive"); |
| 11911 |
|
11911 |
|
| 11912 |
// RAII object to make sure parsed operands are deleted. |
11912 |
// RAII object to make sure parsed operands are deleted. |
| 11913 |
SmallVector, 1> Operands; |
11913 |
SmallVector, 1> Operands; |
| 11914 |
|
11914 |
|
| 11915 |
// Parse the register list |
11915 |
// Parse the register list |
| 11916 |
if (parseRegisterList(Operands, true, true) || parseEOL()) |
11916 |
if (parseRegisterList(Operands, true, true) || parseEOL()) |
| 11917 |
return true; |
11917 |
return true; |
| 11918 |
ARMOperand &Op = (ARMOperand &)*Operands[0]; |
11918 |
ARMOperand &Op = (ARMOperand &)*Operands[0]; |
| 11919 |
if (!IsVector && !Op.isRegList()) |
11919 |
if (!IsVector && !Op.isRegList()) |
| 11920 |
return Error(L, ".save expects GPR registers"); |
11920 |
return Error(L, ".save expects GPR registers"); |
| 11921 |
if (IsVector && !Op.isDPRRegList()) |
11921 |
if (IsVector && !Op.isDPRRegList()) |
| 11922 |
return Error(L, ".vsave expects DPR registers"); |
11922 |
return Error(L, ".vsave expects DPR registers"); |
| 11923 |
|
11923 |
|
| 11924 |
getTargetStreamer().emitRegSave(Op.getRegList(), IsVector); |
11924 |
getTargetStreamer().emitRegSave(Op.getRegList(), IsVector); |
| 11925 |
return false; |
11925 |
return false; |
| 11926 |
} |
11926 |
} |
| 11927 |
|
11927 |
|
| 11928 |
/// parseDirectiveInst |
11928 |
/// parseDirectiveInst |
| 11929 |
/// ::= .inst opcode [, ...] |
11929 |
/// ::= .inst opcode [, ...] |
| 11930 |
/// ::= .inst.n opcode [, ...] |
11930 |
/// ::= .inst.n opcode [, ...] |
| 11931 |
/// ::= .inst.w opcode [, ...] |
11931 |
/// ::= .inst.w opcode [, ...] |
| 11932 |
bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) { |
11932 |
bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) { |
| 11933 |
int Width = 4; |
11933 |
int Width = 4; |
| 11934 |
|
11934 |
|
| 11935 |
if (isThumb()) { |
11935 |
if (isThumb()) { |
| 11936 |
switch (Suffix) { |
11936 |
switch (Suffix) { |
| 11937 |
case 'n': |
11937 |
case 'n': |
| 11938 |
Width = 2; |
11938 |
Width = 2; |
| 11939 |
break; |
11939 |
break; |
| 11940 |
case 'w': |
11940 |
case 'w': |
| 11941 |
break; |
11941 |
break; |
| 11942 |
default: |
11942 |
default: |
| 11943 |
Width = 0; |
11943 |
Width = 0; |
| 11944 |
break; |
11944 |
break; |
| 11945 |
} |
11945 |
} |
| 11946 |
} else { |
11946 |
} else { |
| 11947 |
if (Suffix) |
11947 |
if (Suffix) |
| 11948 |
return Error(Loc, "width suffixes are invalid in ARM mode"); |
11948 |
return Error(Loc, "width suffixes are invalid in ARM mode"); |
| 11949 |
} |
11949 |
} |
| 11950 |
|
11950 |
|
| 11951 |
auto parseOne = [&]() -> bool { |
11951 |
auto parseOne = [&]() -> bool { |
| 11952 |
const MCExpr *Expr; |
11952 |
const MCExpr *Expr; |
| 11953 |
if (getParser().parseExpression(Expr)) |
11953 |
if (getParser().parseExpression(Expr)) |
| 11954 |
return true; |
11954 |
return true; |
| 11955 |
const MCConstantExpr *Value = dyn_cast_or_null(Expr); |
11955 |
const MCConstantExpr *Value = dyn_cast_or_null(Expr); |
| 11956 |
if (!Value) { |
11956 |
if (!Value) { |
| 11957 |
return Error(Loc, "expected constant expression"); |
11957 |
return Error(Loc, "expected constant expression"); |
| 11958 |
} |
11958 |
} |
| 11959 |
|
11959 |
|
| 11960 |
char CurSuffix = Suffix; |
11960 |
char CurSuffix = Suffix; |
| 11961 |
switch (Width) { |
11961 |
switch (Width) { |
| 11962 |
case 2: |
11962 |
case 2: |
| 11963 |
if (Value->getValue() > 0xffff) |
11963 |
if (Value->getValue() > 0xffff) |
| 11964 |
return Error(Loc, "inst.n operand is too big, use inst.w instead"); |
11964 |
return Error(Loc, "inst.n operand is too big, use inst.w instead"); |
| 11965 |
break; |
11965 |
break; |
| 11966 |
case 4: |
11966 |
case 4: |
| 11967 |
if (Value->getValue() > 0xffffffff) |
11967 |
if (Value->getValue() > 0xffffffff) |
| 11968 |
return Error(Loc, StringRef(Suffix ? "inst.w" : "inst") + |
11968 |
return Error(Loc, StringRef(Suffix ? "inst.w" : "inst") + |
| 11969 |
" operand is too big"); |
11969 |
" operand is too big"); |
| 11970 |
break; |
11970 |
break; |
| 11971 |
case 0: |
11971 |
case 0: |
| 11972 |
// Thumb mode, no width indicated. Guess from the opcode, if possible. |
11972 |
// Thumb mode, no width indicated. Guess from the opcode, if possible. |
| 11973 |
if (Value->getValue() < 0xe800) |
11973 |
if (Value->getValue() < 0xe800) |
| 11974 |
CurSuffix = 'n'; |
11974 |
CurSuffix = 'n'; |
| 11975 |
else if (Value->getValue() >= 0xe8000000) |
11975 |
else if (Value->getValue() >= 0xe8000000) |
| 11976 |
CurSuffix = 'w'; |
11976 |
CurSuffix = 'w'; |
| 11977 |
else |
11977 |
else |
| 11978 |
return Error(Loc, "cannot determine Thumb instruction size, " |
11978 |
return Error(Loc, "cannot determine Thumb instruction size, " |
| 11979 |
"use inst.n/inst.w instead"); |
11979 |
"use inst.n/inst.w instead"); |
| 11980 |
break; |
11980 |
break; |
| 11981 |
default: |
11981 |
default: |
| 11982 |
llvm_unreachable("only supported widths are 2 and 4"); |
11982 |
llvm_unreachable("only supported widths are 2 and 4"); |
| 11983 |
} |
11983 |
} |
| 11984 |
|
11984 |
|
| 11985 |
getTargetStreamer().emitInst(Value->getValue(), CurSuffix); |
11985 |
getTargetStreamer().emitInst(Value->getValue(), CurSuffix); |
| 11986 |
return false; |
11986 |
return false; |
| 11987 |
}; |
11987 |
}; |
| 11988 |
|
11988 |
|
| 11989 |
if (parseOptionalToken(AsmToken::EndOfStatement)) |
11989 |
if (parseOptionalToken(AsmToken::EndOfStatement)) |
| 11990 |
return Error(Loc, "expected expression following directive"); |
11990 |
return Error(Loc, "expected expression following directive"); |
| 11991 |
if (parseMany(parseOne)) |
11991 |
if (parseMany(parseOne)) |
| 11992 |
return true; |
11992 |
return true; |
| 11993 |
return false; |
11993 |
return false; |
| 11994 |
} |
11994 |
} |
| 11995 |
|
11995 |
|
| 11996 |
/// parseDirectiveLtorg |
11996 |
/// parseDirectiveLtorg |
| 11997 |
/// ::= .ltorg | .pool |
11997 |
/// ::= .ltorg | .pool |
| 11998 |
bool ARMAsmParser::parseDirectiveLtorg(SMLoc L) { |
11998 |
bool ARMAsmParser::parseDirectiveLtorg(SMLoc L) { |
| 11999 |
if (parseEOL()) |
11999 |
if (parseEOL()) |
| 12000 |
return true; |
12000 |
return true; |
| 12001 |
getTargetStreamer().emitCurrentConstantPool(); |
12001 |
getTargetStreamer().emitCurrentConstantPool(); |
| 12002 |
return false; |
12002 |
return false; |
| 12003 |
} |
12003 |
} |
| 12004 |
|
12004 |
|
| 12005 |
bool ARMAsmParser::parseDirectiveEven(SMLoc L) { |
12005 |
bool ARMAsmParser::parseDirectiveEven(SMLoc L) { |
| 12006 |
const MCSection *Section = getStreamer().getCurrentSectionOnly(); |
12006 |
const MCSection *Section = getStreamer().getCurrentSectionOnly(); |
| 12007 |
|
12007 |
|
| 12008 |
if (parseEOL()) |
12008 |
if (parseEOL()) |
| 12009 |
return true; |
12009 |
return true; |
| 12010 |
|
12010 |
|
| 12011 |
if (!Section) { |
12011 |
if (!Section) { |
| 12012 |
getStreamer().initSections(false, getSTI()); |
12012 |
getStreamer().initSections(false, getSTI()); |
| 12013 |
Section = getStreamer().getCurrentSectionOnly(); |
12013 |
Section = getStreamer().getCurrentSectionOnly(); |
| 12014 |
} |
12014 |
} |
| 12015 |
|
12015 |
|
| 12016 |
assert(Section && "must have section to emit alignment"); |
12016 |
assert(Section && "must have section to emit alignment"); |
| 12017 |
if (Section->useCodeAlign()) |
12017 |
if (Section->useCodeAlign()) |
| 12018 |
getStreamer().emitCodeAlignment(Align(2), &getSTI()); |
12018 |
getStreamer().emitCodeAlignment(Align(2), &getSTI()); |
| 12019 |
else |
12019 |
else |
| 12020 |
getStreamer().emitValueToAlignment(Align(2)); |
12020 |
getStreamer().emitValueToAlignment(Align(2)); |
| 12021 |
|
12021 |
|
| 12022 |
return false; |
12022 |
return false; |
| 12023 |
} |
12023 |
} |
| 12024 |
|
12024 |
|
| 12025 |
/// parseDirectivePersonalityIndex |
12025 |
/// parseDirectivePersonalityIndex |
| 12026 |
/// ::= .personalityindex index |
12026 |
/// ::= .personalityindex index |
| 12027 |
bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) { |
12027 |
bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) { |
| 12028 |
MCAsmParser &Parser = getParser(); |
12028 |
MCAsmParser &Parser = getParser(); |
| 12029 |
bool HasExistingPersonality = UC.hasPersonality(); |
12029 |
bool HasExistingPersonality = UC.hasPersonality(); |
| 12030 |
|
12030 |
|
| 12031 |
const MCExpr *IndexExpression; |
12031 |
const MCExpr *IndexExpression; |
| 12032 |
SMLoc IndexLoc = Parser.getTok().getLoc(); |
12032 |
SMLoc IndexLoc = Parser.getTok().getLoc(); |
| 12033 |
if (Parser.parseExpression(IndexExpression) || parseEOL()) { |
12033 |
if (Parser.parseExpression(IndexExpression) || parseEOL()) { |
| 12034 |
return true; |
12034 |
return true; |
| 12035 |
} |
12035 |
} |
| 12036 |
|
12036 |
|
| 12037 |
UC.recordPersonalityIndex(L); |
12037 |
UC.recordPersonalityIndex(L); |
| 12038 |
|
12038 |
|
| 12039 |
if (!UC.hasFnStart()) { |
12039 |
if (!UC.hasFnStart()) { |
| 12040 |
return Error(L, ".fnstart must precede .personalityindex directive"); |
12040 |
return Error(L, ".fnstart must precede .personalityindex directive"); |
| 12041 |
} |
12041 |
} |
| 12042 |
if (UC.cantUnwind()) { |
12042 |
if (UC.cantUnwind()) { |
| 12043 |
Error(L, ".personalityindex cannot be used with .cantunwind"); |
12043 |
Error(L, ".personalityindex cannot be used with .cantunwind"); |
| 12044 |
UC.emitCantUnwindLocNotes(); |
12044 |
UC.emitCantUnwindLocNotes(); |
| 12045 |
return true; |
12045 |
return true; |
| 12046 |
} |
12046 |
} |
| 12047 |
if (UC.hasHandlerData()) { |
12047 |
if (UC.hasHandlerData()) { |
| 12048 |
Error(L, ".personalityindex must precede .handlerdata directive"); |
12048 |
Error(L, ".personalityindex must precede .handlerdata directive"); |
| 12049 |
UC.emitHandlerDataLocNotes(); |
12049 |
UC.emitHandlerDataLocNotes(); |
| 12050 |
return true; |
12050 |
return true; |
| 12051 |
} |
12051 |
} |
| 12052 |
if (HasExistingPersonality) { |
12052 |
if (HasExistingPersonality) { |
| 12053 |
Error(L, "multiple personality directives"); |
12053 |
Error(L, "multiple personality directives"); |
| 12054 |
UC.emitPersonalityLocNotes(); |
12054 |
UC.emitPersonalityLocNotes(); |
| 12055 |
return true; |
12055 |
return true; |
| 12056 |
} |
12056 |
} |
| 12057 |
|
12057 |
|
| 12058 |
const MCConstantExpr *CE = dyn_cast(IndexExpression); |
12058 |
const MCConstantExpr *CE = dyn_cast(IndexExpression); |
| 12059 |
if (!CE) |
12059 |
if (!CE) |
| 12060 |
return Error(IndexLoc, "index must be a constant number"); |
12060 |
return Error(IndexLoc, "index must be a constant number"); |
| 12061 |
if (CE->getValue() < 0 || CE->getValue() >= ARM::EHABI::NUM_PERSONALITY_INDEX) |
12061 |
if (CE->getValue() < 0 || CE->getValue() >= ARM::EHABI::NUM_PERSONALITY_INDEX) |
| 12062 |
return Error(IndexLoc, |
12062 |
return Error(IndexLoc, |
| 12063 |
"personality routine index should be in range [0-3]"); |
12063 |
"personality routine index should be in range [0-3]"); |
| 12064 |
|
12064 |
|
| 12065 |
getTargetStreamer().emitPersonalityIndex(CE->getValue()); |
12065 |
getTargetStreamer().emitPersonalityIndex(CE->getValue()); |
| 12066 |
return false; |
12066 |
return false; |
| 12067 |
} |
12067 |
} |
| 12068 |
|
12068 |
|
| 12069 |
/// parseDirectiveUnwindRaw |
12069 |
/// parseDirectiveUnwindRaw |
| 12070 |
/// ::= .unwind_raw offset, opcode [, opcode...] |
12070 |
/// ::= .unwind_raw offset, opcode [, opcode...] |
| 12071 |
bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) { |
12071 |
bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) { |
| 12072 |
MCAsmParser &Parser = getParser(); |
12072 |
MCAsmParser &Parser = getParser(); |
| 12073 |
int64_t StackOffset; |
12073 |
int64_t StackOffset; |
| 12074 |
const MCExpr *OffsetExpr; |
12074 |
const MCExpr *OffsetExpr; |
| 12075 |
SMLoc OffsetLoc = getLexer().getLoc(); |
12075 |
SMLoc OffsetLoc = getLexer().getLoc(); |
| 12076 |
|
12076 |
|
| 12077 |
if (!UC.hasFnStart()) |
12077 |
if (!UC.hasFnStart()) |
| 12078 |
return Error(L, ".fnstart must precede .unwind_raw directives"); |
12078 |
return Error(L, ".fnstart must precede .unwind_raw directives"); |
| 12079 |
if (getParser().parseExpression(OffsetExpr)) |
12079 |
if (getParser().parseExpression(OffsetExpr)) |
| 12080 |
return Error(OffsetLoc, "expected expression"); |
12080 |
return Error(OffsetLoc, "expected expression"); |
| 12081 |
|
12081 |
|
| 12082 |
const MCConstantExpr *CE = dyn_cast(OffsetExpr); |
12082 |
const MCConstantExpr *CE = dyn_cast(OffsetExpr); |
| 12083 |
if (!CE) |
12083 |
if (!CE) |
| 12084 |
return Error(OffsetLoc, "offset must be a constant"); |
12084 |
return Error(OffsetLoc, "offset must be a constant"); |
| 12085 |
|
12085 |
|
| 12086 |
StackOffset = CE->getValue(); |
12086 |
StackOffset = CE->getValue(); |
| 12087 |
|
12087 |
|
| 12088 |
if (Parser.parseComma()) |
12088 |
if (Parser.parseComma()) |
| 12089 |
return true; |
12089 |
return true; |
| 12090 |
|
12090 |
|
| 12091 |
SmallVector Opcodes; |
12091 |
SmallVector Opcodes; |
| 12092 |
|
12092 |
|
| 12093 |
auto parseOne = [&]() -> bool { |
12093 |
auto parseOne = [&]() -> bool { |
| 12094 |
const MCExpr *OE = nullptr; |
12094 |
const MCExpr *OE = nullptr; |
| 12095 |
SMLoc OpcodeLoc = getLexer().getLoc(); |
12095 |
SMLoc OpcodeLoc = getLexer().getLoc(); |
| 12096 |
if (check(getLexer().is(AsmToken::EndOfStatement) || |
12096 |
if (check(getLexer().is(AsmToken::EndOfStatement) || |
| 12097 |
Parser.parseExpression(OE), |
12097 |
Parser.parseExpression(OE), |
| 12098 |
OpcodeLoc, "expected opcode expression")) |
12098 |
OpcodeLoc, "expected opcode expression")) |
| 12099 |
return true; |
12099 |
return true; |
| 12100 |
const MCConstantExpr *OC = dyn_cast(OE); |
12100 |
const MCConstantExpr *OC = dyn_cast(OE); |
| 12101 |
if (!OC) |
12101 |
if (!OC) |
| 12102 |
return Error(OpcodeLoc, "opcode value must be a constant"); |
12102 |
return Error(OpcodeLoc, "opcode value must be a constant"); |
| 12103 |
const int64_t Opcode = OC->getValue(); |
12103 |
const int64_t Opcode = OC->getValue(); |
| 12104 |
if (Opcode & ~0xff) |
12104 |
if (Opcode & ~0xff) |
| 12105 |
return Error(OpcodeLoc, "invalid opcode"); |
12105 |
return Error(OpcodeLoc, "invalid opcode"); |
| 12106 |
Opcodes.push_back(uint8_t(Opcode)); |
12106 |
Opcodes.push_back(uint8_t(Opcode)); |
| 12107 |
return false; |
12107 |
return false; |
| 12108 |
}; |
12108 |
}; |
| 12109 |
|
12109 |
|
| 12110 |
// Must have at least 1 element |
12110 |
// Must have at least 1 element |
| 12111 |
SMLoc OpcodeLoc = getLexer().getLoc(); |
12111 |
SMLoc OpcodeLoc = getLexer().getLoc(); |
| 12112 |
if (parseOptionalToken(AsmToken::EndOfStatement)) |
12112 |
if (parseOptionalToken(AsmToken::EndOfStatement)) |
| 12113 |
return Error(OpcodeLoc, "expected opcode expression"); |
12113 |
return Error(OpcodeLoc, "expected opcode expression"); |
| 12114 |
if (parseMany(parseOne)) |
12114 |
if (parseMany(parseOne)) |
| 12115 |
return true; |
12115 |
return true; |
| 12116 |
|
12116 |
|
| 12117 |
getTargetStreamer().emitUnwindRaw(StackOffset, Opcodes); |
12117 |
getTargetStreamer().emitUnwindRaw(StackOffset, Opcodes); |
| 12118 |
return false; |
12118 |
return false; |
| 12119 |
} |
12119 |
} |
| 12120 |
|
12120 |
|
| 12121 |
/// parseDirectiveTLSDescSeq |
12121 |
/// parseDirectiveTLSDescSeq |
| 12122 |
/// ::= .tlsdescseq tls-variable |
12122 |
/// ::= .tlsdescseq tls-variable |
| 12123 |
bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) { |
12123 |
bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) { |
| 12124 |
MCAsmParser &Parser = getParser(); |
12124 |
MCAsmParser &Parser = getParser(); |
| 12125 |
|
12125 |
|
| 12126 |
if (getLexer().isNot(AsmToken::Identifier)) |
12126 |
if (getLexer().isNot(AsmToken::Identifier)) |
| 12127 |
return TokError("expected variable after '.tlsdescseq' directive"); |
12127 |
return TokError("expected variable after '.tlsdescseq' directive"); |
| 12128 |
|
12128 |
|
| 12129 |
const MCSymbolRefExpr *SRE = |
12129 |
const MCSymbolRefExpr *SRE = |
| 12130 |
MCSymbolRefExpr::create(Parser.getTok().getIdentifier(), |
12130 |
MCSymbolRefExpr::create(Parser.getTok().getIdentifier(), |
| 12131 |
MCSymbolRefExpr::VK_ARM_TLSDESCSEQ, getContext()); |
12131 |
MCSymbolRefExpr::VK_ARM_TLSDESCSEQ, getContext()); |
| 12132 |
Lex(); |
12132 |
Lex(); |
| 12133 |
|
12133 |
|
| 12134 |
if (parseEOL()) |
12134 |
if (parseEOL()) |
| 12135 |
return true; |
12135 |
return true; |
| 12136 |
|
12136 |
|
| 12137 |
getTargetStreamer().annotateTLSDescriptorSequence(SRE); |
12137 |
getTargetStreamer().annotateTLSDescriptorSequence(SRE); |
| 12138 |
return false; |
12138 |
return false; |
| 12139 |
} |
12139 |
} |
| 12140 |
|
12140 |
|
| 12141 |
/// parseDirectiveMovSP |
12141 |
/// parseDirectiveMovSP |
| 12142 |
/// ::= .movsp reg [, #offset] |
12142 |
/// ::= .movsp reg [, #offset] |
| 12143 |
bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) { |
12143 |
bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) { |
| 12144 |
MCAsmParser &Parser = getParser(); |
12144 |
MCAsmParser &Parser = getParser(); |
| 12145 |
if (!UC.hasFnStart()) |
12145 |
if (!UC.hasFnStart()) |
| 12146 |
return Error(L, ".fnstart must precede .movsp directives"); |
12146 |
return Error(L, ".fnstart must precede .movsp directives"); |
| 12147 |
if (UC.getFPReg() != ARM::SP) |
12147 |
if (UC.getFPReg() != ARM::SP) |
| 12148 |
return Error(L, "unexpected .movsp directive"); |
12148 |
return Error(L, "unexpected .movsp directive"); |
| 12149 |
|
12149 |
|
| 12150 |
SMLoc SPRegLoc = Parser.getTok().getLoc(); |
12150 |
SMLoc SPRegLoc = Parser.getTok().getLoc(); |
| 12151 |
int SPReg = tryParseRegister(); |
12151 |
int SPReg = tryParseRegister(); |
| 12152 |
if (SPReg == -1) |
12152 |
if (SPReg == -1) |
| 12153 |
return Error(SPRegLoc, "register expected"); |
12153 |
return Error(SPRegLoc, "register expected"); |
| 12154 |
if (SPReg == ARM::SP || SPReg == ARM::PC) |
12154 |
if (SPReg == ARM::SP || SPReg == ARM::PC) |
| 12155 |
return Error(SPRegLoc, "sp and pc are not permitted in .movsp directive"); |
12155 |
return Error(SPRegLoc, "sp and pc are not permitted in .movsp directive"); |
| 12156 |
|
12156 |
|
| 12157 |
int64_t Offset = 0; |
12157 |
int64_t Offset = 0; |
| 12158 |
if (Parser.parseOptionalToken(AsmToken::Comma)) { |
12158 |
if (Parser.parseOptionalToken(AsmToken::Comma)) { |
| 12159 |
if (Parser.parseToken(AsmToken::Hash, "expected #constant")) |
12159 |
if (Parser.parseToken(AsmToken::Hash, "expected #constant")) |
| 12160 |
return true; |
12160 |
return true; |
| 12161 |
|
12161 |
|
| 12162 |
const MCExpr *OffsetExpr; |
12162 |
const MCExpr *OffsetExpr; |
| 12163 |
SMLoc OffsetLoc = Parser.getTok().getLoc(); |
12163 |
SMLoc OffsetLoc = Parser.getTok().getLoc(); |
| 12164 |
|
12164 |
|
| 12165 |
if (Parser.parseExpression(OffsetExpr)) |
12165 |
if (Parser.parseExpression(OffsetExpr)) |
| 12166 |
return Error(OffsetLoc, "malformed offset expression"); |
12166 |
return Error(OffsetLoc, "malformed offset expression"); |
| 12167 |
|
12167 |
|
| 12168 |
const MCConstantExpr *CE = dyn_cast(OffsetExpr); |
12168 |
const MCConstantExpr *CE = dyn_cast(OffsetExpr); |
| 12169 |
if (!CE) |
12169 |
if (!CE) |
| 12170 |
return Error(OffsetLoc, "offset must be an immediate constant"); |
12170 |
return Error(OffsetLoc, "offset must be an immediate constant"); |
| 12171 |
|
12171 |
|
| 12172 |
Offset = CE->getValue(); |
12172 |
Offset = CE->getValue(); |
| 12173 |
} |
12173 |
} |
| 12174 |
|
12174 |
|
| 12175 |
if (parseEOL()) |
12175 |
if (parseEOL()) |
| 12176 |
return true; |
12176 |
return true; |
| 12177 |
|
12177 |
|
| 12178 |
getTargetStreamer().emitMovSP(SPReg, Offset); |
12178 |
getTargetStreamer().emitMovSP(SPReg, Offset); |
| 12179 |
UC.saveFPReg(SPReg); |
12179 |
UC.saveFPReg(SPReg); |
| 12180 |
|
12180 |
|
| 12181 |
return false; |
12181 |
return false; |
| 12182 |
} |
12182 |
} |
| 12183 |
|
12183 |
|
| 12184 |
/// parseDirectiveObjectArch |
12184 |
/// parseDirectiveObjectArch |
| 12185 |
/// ::= .object_arch name |
12185 |
/// ::= .object_arch name |
| 12186 |
bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) { |
12186 |
bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) { |
| 12187 |
MCAsmParser &Parser = getParser(); |
12187 |
MCAsmParser &Parser = getParser(); |
| 12188 |
if (getLexer().isNot(AsmToken::Identifier)) |
12188 |
if (getLexer().isNot(AsmToken::Identifier)) |
| 12189 |
return Error(getLexer().getLoc(), "unexpected token"); |
12189 |
return Error(getLexer().getLoc(), "unexpected token"); |
| 12190 |
|
12190 |
|
| 12191 |
StringRef Arch = Parser.getTok().getString(); |
12191 |
StringRef Arch = Parser.getTok().getString(); |
| 12192 |
SMLoc ArchLoc = Parser.getTok().getLoc(); |
12192 |
SMLoc ArchLoc = Parser.getTok().getLoc(); |
| 12193 |
Lex(); |
12193 |
Lex(); |
| 12194 |
|
12194 |
|
| 12195 |
ARM::ArchKind ID = ARM::parseArch(Arch); |
12195 |
ARM::ArchKind ID = ARM::parseArch(Arch); |
| 12196 |
|
12196 |
|
| 12197 |
if (ID == ARM::ArchKind::INVALID) |
12197 |
if (ID == ARM::ArchKind::INVALID) |
| 12198 |
return Error(ArchLoc, "unknown architecture '" + Arch + "'"); |
12198 |
return Error(ArchLoc, "unknown architecture '" + Arch + "'"); |
| 12199 |
if (parseToken(AsmToken::EndOfStatement)) |
12199 |
if (parseToken(AsmToken::EndOfStatement)) |
| 12200 |
return true; |
12200 |
return true; |
| 12201 |
|
12201 |
|
| 12202 |
getTargetStreamer().emitObjectArch(ID); |
12202 |
getTargetStreamer().emitObjectArch(ID); |
| 12203 |
return false; |
12203 |
return false; |
| 12204 |
} |
12204 |
} |
| 12205 |
|
12205 |
|
| 12206 |
/// parseDirectiveAlign |
12206 |
/// parseDirectiveAlign |
| 12207 |
/// ::= .align |
12207 |
/// ::= .align |
| 12208 |
bool ARMAsmParser::parseDirectiveAlign(SMLoc L) { |
12208 |
bool ARMAsmParser::parseDirectiveAlign(SMLoc L) { |
| 12209 |
// NOTE: if this is not the end of the statement, fall back to the target |
12209 |
// NOTE: if this is not the end of the statement, fall back to the target |
| 12210 |
// agnostic handling for this directive which will correctly handle this. |
12210 |
// agnostic handling for this directive which will correctly handle this. |
| 12211 |
if (parseOptionalToken(AsmToken::EndOfStatement)) { |
12211 |
if (parseOptionalToken(AsmToken::EndOfStatement)) { |
| 12212 |
// '.align' is target specifically handled to mean 2**2 byte alignment. |
12212 |
// '.align' is target specifically handled to mean 2**2 byte alignment. |
| 12213 |
const MCSection *Section = getStreamer().getCurrentSectionOnly(); |
12213 |
const MCSection *Section = getStreamer().getCurrentSectionOnly(); |
| 12214 |
assert(Section && "must have section to emit alignment"); |
12214 |
assert(Section && "must have section to emit alignment"); |
| 12215 |
if (Section->useCodeAlign()) |
12215 |
if (Section->useCodeAlign()) |
| 12216 |
getStreamer().emitCodeAlignment(Align(4), &getSTI(), 0); |
12216 |
getStreamer().emitCodeAlignment(Align(4), &getSTI(), 0); |
| 12217 |
else |
12217 |
else |
| 12218 |
getStreamer().emitValueToAlignment(Align(4), 0, 1, 0); |
12218 |
getStreamer().emitValueToAlignment(Align(4), 0, 1, 0); |
| 12219 |
return false; |
12219 |
return false; |
| 12220 |
} |
12220 |
} |
| 12221 |
return true; |
12221 |
return true; |
| 12222 |
} |
12222 |
} |
| 12223 |
|
12223 |
|
| 12224 |
/// parseDirectiveThumbSet |
12224 |
/// parseDirectiveThumbSet |
| 12225 |
/// ::= .thumb_set name, value |
12225 |
/// ::= .thumb_set name, value |
| 12226 |
bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) { |
12226 |
bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) { |
| 12227 |
MCAsmParser &Parser = getParser(); |
12227 |
MCAsmParser &Parser = getParser(); |
| 12228 |
|
12228 |
|
| 12229 |
StringRef Name; |
12229 |
StringRef Name; |
| 12230 |
if (check(Parser.parseIdentifier(Name), |
12230 |
if (check(Parser.parseIdentifier(Name), |
| 12231 |
"expected identifier after '.thumb_set'") || |
12231 |
"expected identifier after '.thumb_set'") || |
| 12232 |
Parser.parseComma()) |
12232 |
Parser.parseComma()) |
| 12233 |
return true; |
12233 |
return true; |
| 12234 |
|
12234 |
|
| 12235 |
MCSymbol *Sym; |
12235 |
MCSymbol *Sym; |
| 12236 |
const MCExpr *Value; |
12236 |
const MCExpr *Value; |
| 12237 |
if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true, |
12237 |
if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true, |
| 12238 |
Parser, Sym, Value)) |
12238 |
Parser, Sym, Value)) |
| 12239 |
return true; |
12239 |
return true; |
| 12240 |
|
12240 |
|
| 12241 |
getTargetStreamer().emitThumbSet(Sym, Value); |
12241 |
getTargetStreamer().emitThumbSet(Sym, Value); |
| 12242 |
return false; |
12242 |
return false; |
| 12243 |
} |
12243 |
} |
| 12244 |
|
12244 |
|
| 12245 |
/// parseDirectiveSEHAllocStack |
12245 |
/// parseDirectiveSEHAllocStack |
| 12246 |
/// ::= .seh_stackalloc |
12246 |
/// ::= .seh_stackalloc |
| 12247 |
/// ::= .seh_stackalloc_w |
12247 |
/// ::= .seh_stackalloc_w |
| 12248 |
bool ARMAsmParser::parseDirectiveSEHAllocStack(SMLoc L, bool Wide) { |
12248 |
bool ARMAsmParser::parseDirectiveSEHAllocStack(SMLoc L, bool Wide) { |
| 12249 |
int64_t Size; |
12249 |
int64_t Size; |
| 12250 |
if (parseImmExpr(Size)) |
12250 |
if (parseImmExpr(Size)) |
| 12251 |
return true; |
12251 |
return true; |
| 12252 |
getTargetStreamer().emitARMWinCFIAllocStack(Size, Wide); |
12252 |
getTargetStreamer().emitARMWinCFIAllocStack(Size, Wide); |
| 12253 |
return false; |
12253 |
return false; |
| 12254 |
} |
12254 |
} |
| 12255 |
|
12255 |
|
| 12256 |
/// parseDirectiveSEHSaveRegs |
12256 |
/// parseDirectiveSEHSaveRegs |
| 12257 |
/// ::= .seh_save_regs |
12257 |
/// ::= .seh_save_regs |
| 12258 |
/// ::= .seh_save_regs_w |
12258 |
/// ::= .seh_save_regs_w |
| 12259 |
bool ARMAsmParser::parseDirectiveSEHSaveRegs(SMLoc L, bool Wide) { |
12259 |
bool ARMAsmParser::parseDirectiveSEHSaveRegs(SMLoc L, bool Wide) { |
| 12260 |
SmallVector, 1> Operands; |
12260 |
SmallVector, 1> Operands; |
| 12261 |
|
12261 |
|
| 12262 |
if (parseRegisterList(Operands) || parseEOL()) |
12262 |
if (parseRegisterList(Operands) || parseEOL()) |
| 12263 |
return true; |
12263 |
return true; |
| 12264 |
ARMOperand &Op = (ARMOperand &)*Operands[0]; |
12264 |
ARMOperand &Op = (ARMOperand &)*Operands[0]; |
| 12265 |
if (!Op.isRegList()) |
12265 |
if (!Op.isRegList()) |
| 12266 |
return Error(L, ".seh_save_regs{_w} expects GPR registers"); |
12266 |
return Error(L, ".seh_save_regs{_w} expects GPR registers"); |
| 12267 |
const SmallVectorImpl &RegList = Op.getRegList(); |
12267 |
const SmallVectorImpl &RegList = Op.getRegList(); |
| 12268 |
uint32_t Mask = 0; |
12268 |
uint32_t Mask = 0; |
| 12269 |
for (size_t i = 0; i < RegList.size(); ++i) { |
12269 |
for (size_t i = 0; i < RegList.size(); ++i) { |
| 12270 |
unsigned Reg = MRI->getEncodingValue(RegList[i]); |
12270 |
unsigned Reg = MRI->getEncodingValue(RegList[i]); |
| 12271 |
if (Reg == 15) // pc -> lr |
12271 |
if (Reg == 15) // pc -> lr |
| 12272 |
Reg = 14; |
12272 |
Reg = 14; |
| 12273 |
if (Reg == 13) |
12273 |
if (Reg == 13) |
| 12274 |
return Error(L, ".seh_save_regs{_w} can't include SP"); |
12274 |
return Error(L, ".seh_save_regs{_w} can't include SP"); |
| 12275 |
assert(Reg < 16U && "Register out of range"); |
12275 |
assert(Reg < 16U && "Register out of range"); |
| 12276 |
unsigned Bit = (1u << Reg); |
12276 |
unsigned Bit = (1u << Reg); |
| 12277 |
Mask |= Bit; |
12277 |
Mask |= Bit; |
| 12278 |
} |
12278 |
} |
| 12279 |
if (!Wide && (Mask & 0x1f00) != 0) |
12279 |
if (!Wide && (Mask & 0x1f00) != 0) |
| 12280 |
return Error(L, |
12280 |
return Error(L, |
| 12281 |
".seh_save_regs cannot save R8-R12, needs .seh_save_regs_w"); |
12281 |
".seh_save_regs cannot save R8-R12, needs .seh_save_regs_w"); |
| 12282 |
getTargetStreamer().emitARMWinCFISaveRegMask(Mask, Wide); |
12282 |
getTargetStreamer().emitARMWinCFISaveRegMask(Mask, Wide); |
| 12283 |
return false; |
12283 |
return false; |
| 12284 |
} |
12284 |
} |
| 12285 |
|
12285 |
|
| 12286 |
/// parseDirectiveSEHSaveSP |
12286 |
/// parseDirectiveSEHSaveSP |
| 12287 |
/// ::= .seh_save_sp |
12287 |
/// ::= .seh_save_sp |
| 12288 |
bool ARMAsmParser::parseDirectiveSEHSaveSP(SMLoc L) { |
12288 |
bool ARMAsmParser::parseDirectiveSEHSaveSP(SMLoc L) { |
| 12289 |
int Reg = tryParseRegister(); |
12289 |
int Reg = tryParseRegister(); |
| 12290 |
if (Reg == -1 || !MRI->getRegClass(ARM::GPRRegClassID).contains(Reg)) |
12290 |
if (Reg == -1 || !MRI->getRegClass(ARM::GPRRegClassID).contains(Reg)) |
| 12291 |
return Error(L, "expected GPR"); |
12291 |
return Error(L, "expected GPR"); |
| 12292 |
unsigned Index = MRI->getEncodingValue(Reg); |
12292 |
unsigned Index = MRI->getEncodingValue(Reg); |
| 12293 |
if (Index > 14 || Index == 13) |
12293 |
if (Index > 14 || Index == 13) |
| 12294 |
return Error(L, "invalid register for .seh_save_sp"); |
12294 |
return Error(L, "invalid register for .seh_save_sp"); |
| 12295 |
getTargetStreamer().emitARMWinCFISaveSP(Index); |
12295 |
getTargetStreamer().emitARMWinCFISaveSP(Index); |
| 12296 |
return false; |
12296 |
return false; |
| 12297 |
} |
12297 |
} |
| 12298 |
|
12298 |
|
| 12299 |
/// parseDirectiveSEHSaveFRegs |
12299 |
/// parseDirectiveSEHSaveFRegs |
| 12300 |
/// ::= .seh_save_fregs |
12300 |
/// ::= .seh_save_fregs |
| 12301 |
bool ARMAsmParser::parseDirectiveSEHSaveFRegs(SMLoc L) { |
12301 |
bool ARMAsmParser::parseDirectiveSEHSaveFRegs(SMLoc L) { |
| 12302 |
SmallVector, 1> Operands; |
12302 |
SmallVector, 1> Operands; |
| 12303 |
|
12303 |
|
| 12304 |
if (parseRegisterList(Operands) || parseEOL()) |
12304 |
if (parseRegisterList(Operands) || parseEOL()) |
| 12305 |
return true; |
12305 |
return true; |
| 12306 |
ARMOperand &Op = (ARMOperand &)*Operands[0]; |
12306 |
ARMOperand &Op = (ARMOperand &)*Operands[0]; |
| 12307 |
if (!Op.isDPRRegList()) |
12307 |
if (!Op.isDPRRegList()) |
| 12308 |
return Error(L, ".seh_save_fregs expects DPR registers"); |
12308 |
return Error(L, ".seh_save_fregs expects DPR registers"); |
| 12309 |
const SmallVectorImpl &RegList = Op.getRegList(); |
12309 |
const SmallVectorImpl &RegList = Op.getRegList(); |
| 12310 |
uint32_t Mask = 0; |
12310 |
uint32_t Mask = 0; |
| 12311 |
for (size_t i = 0; i < RegList.size(); ++i) { |
12311 |
for (size_t i = 0; i < RegList.size(); ++i) { |
| 12312 |
unsigned Reg = MRI->getEncodingValue(RegList[i]); |
12312 |
unsigned Reg = MRI->getEncodingValue(RegList[i]); |
| 12313 |
assert(Reg < 32U && "Register out of range"); |
12313 |
assert(Reg < 32U && "Register out of range"); |
| 12314 |
unsigned Bit = (1u << Reg); |
12314 |
unsigned Bit = (1u << Reg); |
| 12315 |
Mask |= Bit; |
12315 |
Mask |= Bit; |
| 12316 |
} |
12316 |
} |
| 12317 |
|
12317 |
|
| 12318 |
if (Mask == 0) |
12318 |
if (Mask == 0) |
| 12319 |
return Error(L, ".seh_save_fregs missing registers"); |
12319 |
return Error(L, ".seh_save_fregs missing registers"); |
| 12320 |
|
12320 |
|
| 12321 |
unsigned First = 0; |
12321 |
unsigned First = 0; |
| 12322 |
while ((Mask & 1) == 0) { |
12322 |
while ((Mask & 1) == 0) { |
| 12323 |
First++; |
12323 |
First++; |
| 12324 |
Mask >>= 1; |
12324 |
Mask >>= 1; |
| 12325 |
} |
12325 |
} |
| 12326 |
if (((Mask + 1) & Mask) != 0) |
12326 |
if (((Mask + 1) & Mask) != 0) |
| 12327 |
return Error(L, |
12327 |
return Error(L, |
| 12328 |
".seh_save_fregs must take a contiguous range of registers"); |
12328 |
".seh_save_fregs must take a contiguous range of registers"); |
| 12329 |
unsigned Last = First; |
12329 |
unsigned Last = First; |
| 12330 |
while ((Mask & 2) != 0) { |
12330 |
while ((Mask & 2) != 0) { |
| 12331 |
Last++; |
12331 |
Last++; |
| 12332 |
Mask >>= 1; |
12332 |
Mask >>= 1; |
| 12333 |
} |
12333 |
} |
| 12334 |
if (First < 16 && Last >= 16) |
12334 |
if (First < 16 && Last >= 16) |
| 12335 |
return Error(L, ".seh_save_fregs must be all d0-d15 or d16-d31"); |
12335 |
return Error(L, ".seh_save_fregs must be all d0-d15 or d16-d31"); |
| 12336 |
getTargetStreamer().emitARMWinCFISaveFRegs(First, Last); |
12336 |
getTargetStreamer().emitARMWinCFISaveFRegs(First, Last); |
| 12337 |
return false; |
12337 |
return false; |
| 12338 |
} |
12338 |
} |
| 12339 |
|
12339 |
|
| 12340 |
/// parseDirectiveSEHSaveLR |
12340 |
/// parseDirectiveSEHSaveLR |
| 12341 |
/// ::= .seh_save_lr |
12341 |
/// ::= .seh_save_lr |
| 12342 |
bool ARMAsmParser::parseDirectiveSEHSaveLR(SMLoc L) { |
12342 |
bool ARMAsmParser::parseDirectiveSEHSaveLR(SMLoc L) { |
| 12343 |
int64_t Offset; |
12343 |
int64_t Offset; |
| 12344 |
if (parseImmExpr(Offset)) |
12344 |
if (parseImmExpr(Offset)) |
| 12345 |
return true; |
12345 |
return true; |
| 12346 |
getTargetStreamer().emitARMWinCFISaveLR(Offset); |
12346 |
getTargetStreamer().emitARMWinCFISaveLR(Offset); |
| 12347 |
return false; |
12347 |
return false; |
| 12348 |
} |
12348 |
} |
| 12349 |
|
12349 |
|
| 12350 |
/// parseDirectiveSEHPrologEnd |
12350 |
/// parseDirectiveSEHPrologEnd |
| 12351 |
/// ::= .seh_endprologue |
12351 |
/// ::= .seh_endprologue |
| 12352 |
/// ::= .seh_endprologue_fragment |
12352 |
/// ::= .seh_endprologue_fragment |
| 12353 |
bool ARMAsmParser::parseDirectiveSEHPrologEnd(SMLoc L, bool Fragment) { |
12353 |
bool ARMAsmParser::parseDirectiveSEHPrologEnd(SMLoc L, bool Fragment) { |
| 12354 |
getTargetStreamer().emitARMWinCFIPrologEnd(Fragment); |
12354 |
getTargetStreamer().emitARMWinCFIPrologEnd(Fragment); |
| 12355 |
return false; |
12355 |
return false; |
| 12356 |
} |
12356 |
} |
| 12357 |
|
12357 |
|
| 12358 |
/// parseDirectiveSEHNop |
12358 |
/// parseDirectiveSEHNop |
| 12359 |
/// ::= .seh_nop |
12359 |
/// ::= .seh_nop |
| 12360 |
/// ::= .seh_nop_w |
12360 |
/// ::= .seh_nop_w |
| 12361 |
bool ARMAsmParser::parseDirectiveSEHNop(SMLoc L, bool Wide) { |
12361 |
bool ARMAsmParser::parseDirectiveSEHNop(SMLoc L, bool Wide) { |
| 12362 |
getTargetStreamer().emitARMWinCFINop(Wide); |
12362 |
getTargetStreamer().emitARMWinCFINop(Wide); |
| 12363 |
return false; |
12363 |
return false; |
| 12364 |
} |
12364 |
} |
| 12365 |
|
12365 |
|
| 12366 |
/// parseDirectiveSEHEpilogStart |
12366 |
/// parseDirectiveSEHEpilogStart |
| 12367 |
/// ::= .seh_startepilogue |
12367 |
/// ::= .seh_startepilogue |
| 12368 |
/// ::= .seh_startepilogue_cond |
12368 |
/// ::= .seh_startepilogue_cond |
| 12369 |
bool ARMAsmParser::parseDirectiveSEHEpilogStart(SMLoc L, bool Condition) { |
12369 |
bool ARMAsmParser::parseDirectiveSEHEpilogStart(SMLoc L, bool Condition) { |
| 12370 |
unsigned CC = ARMCC::AL; |
12370 |
unsigned CC = ARMCC::AL; |
| 12371 |
if (Condition) { |
12371 |
if (Condition) { |
| 12372 |
MCAsmParser &Parser = getParser(); |
12372 |
MCAsmParser &Parser = getParser(); |
| 12373 |
SMLoc S = Parser.getTok().getLoc(); |
12373 |
SMLoc S = Parser.getTok().getLoc(); |
| 12374 |
const AsmToken &Tok = Parser.getTok(); |
12374 |
const AsmToken &Tok = Parser.getTok(); |
| 12375 |
if (!Tok.is(AsmToken::Identifier)) |
12375 |
if (!Tok.is(AsmToken::Identifier)) |
| 12376 |
return Error(S, ".seh_startepilogue_cond missing condition"); |
12376 |
return Error(S, ".seh_startepilogue_cond missing condition"); |
| 12377 |
CC = ARMCondCodeFromString(Tok.getString()); |
12377 |
CC = ARMCondCodeFromString(Tok.getString()); |
| 12378 |
if (CC == ~0U) |
12378 |
if (CC == ~0U) |
| 12379 |
return Error(S, "invalid condition"); |
12379 |
return Error(S, "invalid condition"); |
| 12380 |
Parser.Lex(); // Eat the token. |
12380 |
Parser.Lex(); // Eat the token. |
| 12381 |
} |
12381 |
} |
| 12382 |
|
12382 |
|
| 12383 |
getTargetStreamer().emitARMWinCFIEpilogStart(CC); |
12383 |
getTargetStreamer().emitARMWinCFIEpilogStart(CC); |
| 12384 |
return false; |
12384 |
return false; |
| 12385 |
} |
12385 |
} |
| 12386 |
|
12386 |
|
| 12387 |
/// parseDirectiveSEHEpilogEnd |
12387 |
/// parseDirectiveSEHEpilogEnd |
| 12388 |
/// ::= .seh_endepilogue |
12388 |
/// ::= .seh_endepilogue |
| 12389 |
bool ARMAsmParser::parseDirectiveSEHEpilogEnd(SMLoc L) { |
12389 |
bool ARMAsmParser::parseDirectiveSEHEpilogEnd(SMLoc L) { |
| 12390 |
getTargetStreamer().emitARMWinCFIEpilogEnd(); |
12390 |
getTargetStreamer().emitARMWinCFIEpilogEnd(); |
| 12391 |
return false; |
12391 |
return false; |
| 12392 |
} |
12392 |
} |
| 12393 |
|
12393 |
|
| 12394 |
/// parseDirectiveSEHCustom |
12394 |
/// parseDirectiveSEHCustom |
| 12395 |
/// ::= .seh_custom |
12395 |
/// ::= .seh_custom |
| 12396 |
bool ARMAsmParser::parseDirectiveSEHCustom(SMLoc L) { |
12396 |
bool ARMAsmParser::parseDirectiveSEHCustom(SMLoc L) { |
| 12397 |
unsigned Opcode = 0; |
12397 |
unsigned Opcode = 0; |
| 12398 |
do { |
12398 |
do { |
| 12399 |
int64_t Byte; |
12399 |
int64_t Byte; |
| 12400 |
if (parseImmExpr(Byte)) |
12400 |
if (parseImmExpr(Byte)) |
| 12401 |
return true; |
12401 |
return true; |
| 12402 |
if (Byte > 0xff || Byte < 0) |
12402 |
if (Byte > 0xff || Byte < 0) |
| 12403 |
return Error(L, "Invalid byte value in .seh_custom"); |
12403 |
return Error(L, "Invalid byte value in .seh_custom"); |
| 12404 |
if (Opcode > 0x00ffffff) |
12404 |
if (Opcode > 0x00ffffff) |
| 12405 |
return Error(L, "Too many bytes in .seh_custom"); |
12405 |
return Error(L, "Too many bytes in .seh_custom"); |
| 12406 |
// Store the bytes as one big endian number in Opcode. In a multi byte |
12406 |
// Store the bytes as one big endian number in Opcode. In a multi byte |
| 12407 |
// opcode sequence, the first byte can't be zero. |
12407 |
// opcode sequence, the first byte can't be zero. |
| 12408 |
Opcode = (Opcode << 8) | Byte; |
12408 |
Opcode = (Opcode << 8) | Byte; |
| 12409 |
} while (parseOptionalToken(AsmToken::Comma)); |
12409 |
} while (parseOptionalToken(AsmToken::Comma)); |
| 12410 |
getTargetStreamer().emitARMWinCFICustom(Opcode); |
12410 |
getTargetStreamer().emitARMWinCFICustom(Opcode); |
| 12411 |
return false; |
12411 |
return false; |
| 12412 |
} |
12412 |
} |
| 12413 |
|
12413 |
|
| 12414 |
/// Force static initialization. |
12414 |
/// Force static initialization. |
| 12415 |
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMAsmParser() { |
12415 |
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMAsmParser() { |
| 12416 |
RegisterMCAsmParser X(getTheARMLETarget()); |
12416 |
RegisterMCAsmParser X(getTheARMLETarget()); |
| 12417 |
RegisterMCAsmParser Y(getTheARMBETarget()); |
12417 |
RegisterMCAsmParser Y(getTheARMBETarget()); |
| 12418 |
RegisterMCAsmParser A(getTheThumbLETarget()); |
12418 |
RegisterMCAsmParser A(getTheThumbLETarget()); |
| 12419 |
RegisterMCAsmParser B(getTheThumbBETarget()); |
12419 |
RegisterMCAsmParser B(getTheThumbBETarget()); |
| 12420 |
} |
12420 |
} |
| 12421 |
|
12421 |
|
| 12422 |
#define GET_REGISTER_MATCHER |
12422 |
#define GET_REGISTER_MATCHER |
| 12423 |
#define GET_SUBTARGET_FEATURE_NAME |
12423 |
#define GET_SUBTARGET_FEATURE_NAME |
| 12424 |
#define GET_MATCHER_IMPLEMENTATION |
12424 |
#define GET_MATCHER_IMPLEMENTATION |
| 12425 |
#define GET_MNEMONIC_SPELL_CHECKER |
12425 |
#define GET_MNEMONIC_SPELL_CHECKER |
| 12426 |
#include "ARMGenAsmMatcher.inc" |
12426 |
#include "ARMGenAsmMatcher.inc" |
| 12427 |
|
12427 |
|
| 12428 |
// Some diagnostics need to vary with subtarget features, so they are handled |
12428 |
// Some diagnostics need to vary with subtarget features, so they are handled |
| 12429 |
// here. For example, the DPR class has either 16 or 32 registers, depending |
12429 |
// here. For example, the DPR class has either 16 or 32 registers, depending |
| 12430 |
// on the FPU available. |
12430 |
// on the FPU available. |
| 12431 |
const char * |
12431 |
const char * |
| 12432 |
ARMAsmParser::getCustomOperandDiag(ARMMatchResultTy MatchError) { |
12432 |
ARMAsmParser::getCustomOperandDiag(ARMMatchResultTy MatchError) { |
| 12433 |
switch (MatchError) { |
12433 |
switch (MatchError) { |
| 12434 |
// rGPR contains sp starting with ARMv8. |
12434 |
// rGPR contains sp starting with ARMv8. |
| 12435 |
case Match_rGPR: |
12435 |
case Match_rGPR: |
| 12436 |
return hasV8Ops() ? "operand must be a register in range [r0, r14]" |
12436 |
return hasV8Ops() ? "operand must be a register in range [r0, r14]" |
| 12437 |
: "operand must be a register in range [r0, r12] or r14"; |
12437 |
: "operand must be a register in range [r0, r12] or r14"; |
| 12438 |
// DPR contains 16 registers for some FPUs, and 32 for others. |
12438 |
// DPR contains 16 registers for some FPUs, and 32 for others. |
| 12439 |
case Match_DPR: |
12439 |
case Match_DPR: |
| 12440 |
return hasD32() ? "operand must be a register in range [d0, d31]" |
12440 |
return hasD32() ? "operand must be a register in range [d0, d31]" |
| 12441 |
: "operand must be a register in range [d0, d15]"; |
12441 |
: "operand must be a register in range [d0, d15]"; |
| 12442 |
case Match_DPR_RegList: |
12442 |
case Match_DPR_RegList: |
| 12443 |
return hasD32() ? "operand must be a list of registers in range [d0, d31]" |
12443 |
return hasD32() ? "operand must be a list of registers in range [d0, d31]" |
| 12444 |
: "operand must be a list of registers in range [d0, d15]"; |
12444 |
: "operand must be a list of registers in range [d0, d15]"; |
| 12445 |
|
12445 |
|
| 12446 |
// For all other diags, use the static string from tablegen. |
12446 |
// For all other diags, use the static string from tablegen. |
| 12447 |
default: |
12447 |
default: |
| 12448 |
return getMatchKindDiag(MatchError); |
12448 |
return getMatchKindDiag(MatchError); |
| 12449 |
} |
12449 |
} |
| 12450 |
} |
12450 |
} |
| 12451 |
|
12451 |
|
| 12452 |
// Process the list of near-misses, throwing away ones we don't want to report |
12452 |
// Process the list of near-misses, throwing away ones we don't want to report |
| 12453 |
// to the user, and converting the rest to a source location and string that |
12453 |
// to the user, and converting the rest to a source location and string that |
| 12454 |
// should be reported. |
12454 |
// should be reported. |
| 12455 |
void |
12455 |
void |
| 12456 |
ARMAsmParser::FilterNearMisses(SmallVectorImpl &NearMissesIn, |
12456 |
ARMAsmParser::FilterNearMisses(SmallVectorImpl &NearMissesIn, |
| 12457 |
SmallVectorImpl &NearMissesOut, |
12457 |
SmallVectorImpl &NearMissesOut, |
| 12458 |
SMLoc IDLoc, OperandVector &Operands) { |
12458 |
SMLoc IDLoc, OperandVector &Operands) { |
| 12459 |
// TODO: If operand didn't match, sub in a dummy one and run target |
12459 |
// TODO: If operand didn't match, sub in a dummy one and run target |
| 12460 |
// predicate, so that we can avoid reporting near-misses that are invalid? |
12460 |
// predicate, so that we can avoid reporting near-misses that are invalid? |
| 12461 |
// TODO: Many operand types dont have SuperClasses set, so we report |
12461 |
// TODO: Many operand types dont have SuperClasses set, so we report |
| 12462 |
// redundant ones. |
12462 |
// redundant ones. |
| 12463 |
// TODO: Some operands are superclasses of registers (e.g. |
12463 |
// TODO: Some operands are superclasses of registers (e.g. |
| 12464 |
// MCK_RegShiftedImm), we don't have any way to represent that currently. |
12464 |
// MCK_RegShiftedImm), we don't have any way to represent that currently. |
| 12465 |
// TODO: This is not all ARM-specific, can some of it be factored out? |
12465 |
// TODO: This is not all ARM-specific, can some of it be factored out? |
| 12466 |
|
12466 |
|
| 12467 |
// Record some information about near-misses that we have already seen, so |
12467 |
// Record some information about near-misses that we have already seen, so |
| 12468 |
// that we can avoid reporting redundant ones. For example, if there are |
12468 |
// that we can avoid reporting redundant ones. For example, if there are |
| 12469 |
// variants of an instruction that take 8- and 16-bit immediates, we want |
12469 |
// variants of an instruction that take 8- and 16-bit immediates, we want |
| 12470 |
// to only report the widest one. |
12470 |
// to only report the widest one. |
| 12471 |
std::multimap OperandMissesSeen; |
12471 |
std::multimap OperandMissesSeen; |
| 12472 |
SmallSet FeatureMissesSeen; |
12472 |
SmallSet FeatureMissesSeen; |
| 12473 |
bool ReportedTooFewOperands = false; |
12473 |
bool ReportedTooFewOperands = false; |
| 12474 |
|
12474 |
|
| 12475 |
// Process the near-misses in reverse order, so that we see more general ones |
12475 |
// Process the near-misses in reverse order, so that we see more general ones |
| 12476 |
// first, and so can avoid emitting more specific ones. |
12476 |
// first, and so can avoid emitting more specific ones. |
| 12477 |
for (NearMissInfo &I : reverse(NearMissesIn)) { |
12477 |
for (NearMissInfo &I : reverse(NearMissesIn)) { |
| 12478 |
switch (I.getKind()) { |
12478 |
switch (I.getKind()) { |
| 12479 |
case NearMissInfo::NearMissOperand: { |
12479 |
case NearMissInfo::NearMissOperand: { |
| 12480 |
SMLoc OperandLoc = |
12480 |
SMLoc OperandLoc = |
| 12481 |
((ARMOperand &)*Operands[I.getOperandIndex()]).getStartLoc(); |
12481 |
((ARMOperand &)*Operands[I.getOperandIndex()]).getStartLoc(); |
| 12482 |
const char *OperandDiag = |
12482 |
const char *OperandDiag = |
| 12483 |
getCustomOperandDiag((ARMMatchResultTy)I.getOperandError()); |
12483 |
getCustomOperandDiag((ARMMatchResultTy)I.getOperandError()); |
| 12484 |
|
12484 |
|
| 12485 |
// If we have already emitted a message for a superclass, don't also report |
12485 |
// If we have already emitted a message for a superclass, don't also report |
| 12486 |
// the sub-class. We consider all operand classes that we don't have a |
12486 |
// the sub-class. We consider all operand classes that we don't have a |
| 12487 |
// specialised diagnostic for to be equal for the propose of this check, |
12487 |
// specialised diagnostic for to be equal for the propose of this check, |
| 12488 |
// so that we don't report the generic error multiple times on the same |
12488 |
// so that we don't report the generic error multiple times on the same |
| 12489 |
// operand. |
12489 |
// operand. |
| 12490 |
unsigned DupCheckMatchClass = OperandDiag ? I.getOperandClass() : ~0U; |
12490 |
unsigned DupCheckMatchClass = OperandDiag ? I.getOperandClass() : ~0U; |
| 12491 |
auto PrevReports = OperandMissesSeen.equal_range(I.getOperandIndex()); |
12491 |
auto PrevReports = OperandMissesSeen.equal_range(I.getOperandIndex()); |
| 12492 |
if (std::any_of(PrevReports.first, PrevReports.second, |
12492 |
if (std::any_of(PrevReports.first, PrevReports.second, |
| 12493 |
[DupCheckMatchClass]( |
12493 |
[DupCheckMatchClass]( |
| 12494 |
const std::pair Pair) { |
12494 |
const std::pair Pair) { |
| 12495 |
if (DupCheckMatchClass == ~0U || Pair.second == ~0U) |
12495 |
if (DupCheckMatchClass == ~0U || Pair.second == ~0U) |
| 12496 |
return Pair.second == DupCheckMatchClass; |
12496 |
return Pair.second == DupCheckMatchClass; |
| 12497 |
else |
12497 |
else |
| 12498 |
return isSubclass((MatchClassKind)DupCheckMatchClass, |
12498 |
return isSubclass((MatchClassKind)DupCheckMatchClass, |
| 12499 |
(MatchClassKind)Pair.second); |
12499 |
(MatchClassKind)Pair.second); |
| 12500 |
})) |
12500 |
})) |
| 12501 |
break; |
12501 |
break; |
| 12502 |
OperandMissesSeen.insert( |
12502 |
OperandMissesSeen.insert( |
| 12503 |
std::make_pair(I.getOperandIndex(), DupCheckMatchClass)); |
12503 |
std::make_pair(I.getOperandIndex(), DupCheckMatchClass)); |
| 12504 |
|
12504 |
|
| 12505 |
NearMissMessage Message; |
12505 |
NearMissMessage Message; |
| 12506 |
Message.Loc = OperandLoc; |
12506 |
Message.Loc = OperandLoc; |
| 12507 |
if (OperandDiag) { |
12507 |
if (OperandDiag) { |
| 12508 |
Message.Message = OperandDiag; |
12508 |
Message.Message = OperandDiag; |
| 12509 |
} else if (I.getOperandClass() == InvalidMatchClass) { |
12509 |
} else if (I.getOperandClass() == InvalidMatchClass) { |
| 12510 |
Message.Message = "too many operands for instruction"; |
12510 |
Message.Message = "too many operands for instruction"; |
| 12511 |
} else { |
12511 |
} else { |
| 12512 |
Message.Message = "invalid operand for instruction"; |
12512 |
Message.Message = "invalid operand for instruction"; |
| 12513 |
LLVM_DEBUG( |
12513 |
LLVM_DEBUG( |
| 12514 |
dbgs() << "Missing diagnostic string for operand class " |
12514 |
dbgs() << "Missing diagnostic string for operand class " |
| 12515 |
<< getMatchClassName((MatchClassKind)I.getOperandClass()) |
12515 |
<< getMatchClassName((MatchClassKind)I.getOperandClass()) |
| 12516 |
<< I.getOperandClass() << ", error " << I.getOperandError() |
12516 |
<< I.getOperandClass() << ", error " << I.getOperandError() |
| 12517 |
<< ", opcode " << MII.getName(I.getOpcode()) << "\n"); |
12517 |
<< ", opcode " << MII.getName(I.getOpcode()) << "\n"); |
| 12518 |
} |
12518 |
} |
| 12519 |
NearMissesOut.emplace_back(Message); |
12519 |
NearMissesOut.emplace_back(Message); |
| 12520 |
break; |
12520 |
break; |
| 12521 |
} |
12521 |
} |
| 12522 |
case NearMissInfo::NearMissFeature: { |
12522 |
case NearMissInfo::NearMissFeature: { |
| 12523 |
const FeatureBitset &MissingFeatures = I.getFeatures(); |
12523 |
const FeatureBitset &MissingFeatures = I.getFeatures(); |
| 12524 |
// Don't report the same set of features twice. |
12524 |
// Don't report the same set of features twice. |
| 12525 |
if (FeatureMissesSeen.count(MissingFeatures)) |
12525 |
if (FeatureMissesSeen.count(MissingFeatures)) |
| 12526 |
break; |
12526 |
break; |
| 12527 |
FeatureMissesSeen.insert(MissingFeatures); |
12527 |
FeatureMissesSeen.insert(MissingFeatures); |
| 12528 |
|
12528 |
|
| 12529 |
// Special case: don't report a feature set which includes arm-mode for |
12529 |
// Special case: don't report a feature set which includes arm-mode for |
| 12530 |
// targets that don't have ARM mode. |
12530 |
// targets that don't have ARM mode. |
| 12531 |
if (MissingFeatures.test(Feature_IsARMBit) && !hasARM()) |
12531 |
if (MissingFeatures.test(Feature_IsARMBit) && !hasARM()) |
| 12532 |
break; |
12532 |
break; |
| 12533 |
// Don't report any near-misses that both require switching instruction |
12533 |
// Don't report any near-misses that both require switching instruction |
| 12534 |
// set, and adding other subtarget features. |
12534 |
// set, and adding other subtarget features. |
| 12535 |
if (isThumb() && MissingFeatures.test(Feature_IsARMBit) && |
12535 |
if (isThumb() && MissingFeatures.test(Feature_IsARMBit) && |
| 12536 |
MissingFeatures.count() > 1) |
12536 |
MissingFeatures.count() > 1) |
| 12537 |
break; |
12537 |
break; |
| 12538 |
if (!isThumb() && MissingFeatures.test(Feature_IsThumbBit) && |
12538 |
if (!isThumb() && MissingFeatures.test(Feature_IsThumbBit) && |
| 12539 |
MissingFeatures.count() > 1) |
12539 |
MissingFeatures.count() > 1) |
| 12540 |
break; |
12540 |
break; |
| 12541 |
if (!isThumb() && MissingFeatures.test(Feature_IsThumb2Bit) && |
12541 |
if (!isThumb() && MissingFeatures.test(Feature_IsThumb2Bit) && |
| 12542 |
(MissingFeatures & ~FeatureBitset({Feature_IsThumb2Bit, |
12542 |
(MissingFeatures & ~FeatureBitset({Feature_IsThumb2Bit, |
| 12543 |
Feature_IsThumbBit})).any()) |
12543 |
Feature_IsThumbBit})).any()) |
| 12544 |
break; |
12544 |
break; |
| 12545 |
if (isMClass() && MissingFeatures.test(Feature_HasNEONBit)) |
12545 |
if (isMClass() && MissingFeatures.test(Feature_HasNEONBit)) |
| 12546 |
break; |
12546 |
break; |
| 12547 |
|
12547 |
|
| 12548 |
NearMissMessage Message; |
12548 |
NearMissMessage Message; |
| 12549 |
Message.Loc = IDLoc; |
12549 |
Message.Loc = IDLoc; |
| 12550 |
raw_svector_ostream OS(Message.Message); |
12550 |
raw_svector_ostream OS(Message.Message); |
| 12551 |
|
12551 |
|
| 12552 |
OS << "instruction requires:"; |
12552 |
OS << "instruction requires:"; |
| 12553 |
for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) |
12553 |
for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) |
| 12554 |
if (MissingFeatures.test(i)) |
12554 |
if (MissingFeatures.test(i)) |
| 12555 |
OS << ' ' << getSubtargetFeatureName(i); |
12555 |
OS << ' ' << getSubtargetFeatureName(i); |
| 12556 |
|
12556 |
|
| 12557 |
NearMissesOut.emplace_back(Message); |
12557 |
NearMissesOut.emplace_back(Message); |
| 12558 |
|
12558 |
|
| 12559 |
break; |
12559 |
break; |
| 12560 |
} |
12560 |
} |
| 12561 |
case NearMissInfo::NearMissPredicate: { |
12561 |
case NearMissInfo::NearMissPredicate: { |
| 12562 |
NearMissMessage Message; |
12562 |
NearMissMessage Message; |
| 12563 |
Message.Loc = IDLoc; |
12563 |
Message.Loc = IDLoc; |
| 12564 |
switch (I.getPredicateError()) { |
12564 |
switch (I.getPredicateError()) { |
| 12565 |
case Match_RequiresNotITBlock: |
12565 |
case Match_RequiresNotITBlock: |
| 12566 |
Message.Message = "flag setting instruction only valid outside IT block"; |
12566 |
Message.Message = "flag setting instruction only valid outside IT block"; |
| 12567 |
break; |
12567 |
break; |
| 12568 |
case Match_RequiresITBlock: |
12568 |
case Match_RequiresITBlock: |
| 12569 |
Message.Message = "instruction only valid inside IT block"; |
12569 |
Message.Message = "instruction only valid inside IT block"; |
| 12570 |
break; |
12570 |
break; |
| 12571 |
case Match_RequiresV6: |
12571 |
case Match_RequiresV6: |
| 12572 |
Message.Message = "instruction variant requires ARMv6 or later"; |
12572 |
Message.Message = "instruction variant requires ARMv6 or later"; |
| 12573 |
break; |
12573 |
break; |
| 12574 |
case Match_RequiresThumb2: |
12574 |
case Match_RequiresThumb2: |
| 12575 |
Message.Message = "instruction variant requires Thumb2"; |
12575 |
Message.Message = "instruction variant requires Thumb2"; |
| 12576 |
break; |
12576 |
break; |
| 12577 |
case Match_RequiresV8: |
12577 |
case Match_RequiresV8: |
| 12578 |
Message.Message = "instruction variant requires ARMv8 or later"; |
12578 |
Message.Message = "instruction variant requires ARMv8 or later"; |
| 12579 |
break; |
12579 |
break; |
| 12580 |
case Match_RequiresFlagSetting: |
12580 |
case Match_RequiresFlagSetting: |
| 12581 |
Message.Message = "no flag-preserving variant of this instruction available"; |
12581 |
Message.Message = "no flag-preserving variant of this instruction available"; |
| 12582 |
break; |
12582 |
break; |
| 12583 |
case Match_InvalidOperand: |
12583 |
case Match_InvalidOperand: |
| 12584 |
Message.Message = "invalid operand for instruction"; |
12584 |
Message.Message = "invalid operand for instruction"; |
| 12585 |
break; |
12585 |
break; |
| 12586 |
default: |
12586 |
default: |
| 12587 |
llvm_unreachable("Unhandled target predicate error"); |
12587 |
llvm_unreachable("Unhandled target predicate error"); |
| 12588 |
break; |
12588 |
break; |
| 12589 |
} |
12589 |
} |
| 12590 |
NearMissesOut.emplace_back(Message); |
12590 |
NearMissesOut.emplace_back(Message); |
| 12591 |
break; |
12591 |
break; |
| 12592 |
} |
12592 |
} |
| 12593 |
case NearMissInfo::NearMissTooFewOperands: { |
12593 |
case NearMissInfo::NearMissTooFewOperands: { |
| 12594 |
if (!ReportedTooFewOperands) { |
12594 |
if (!ReportedTooFewOperands) { |
| 12595 |
SMLoc EndLoc = ((ARMOperand &)*Operands.back()).getEndLoc(); |
12595 |
SMLoc EndLoc = ((ARMOperand &)*Operands.back()).getEndLoc(); |
| 12596 |
NearMissesOut.emplace_back(NearMissMessage{ |
12596 |
NearMissesOut.emplace_back(NearMissMessage{ |
| 12597 |
EndLoc, StringRef("too few operands for instruction")}); |
12597 |
EndLoc, StringRef("too few operands for instruction")}); |
| 12598 |
ReportedTooFewOperands = true; |
12598 |
ReportedTooFewOperands = true; |
| 12599 |
} |
12599 |
} |
| 12600 |
break; |
12600 |
break; |
| 12601 |
} |
12601 |
} |
| 12602 |
case NearMissInfo::NoNearMiss: |
12602 |
case NearMissInfo::NoNearMiss: |
| 12603 |
// This should never leave the matcher. |
12603 |
// This should never leave the matcher. |
| 12604 |
llvm_unreachable("not a near-miss"); |
12604 |
llvm_unreachable("not a near-miss"); |
| 12605 |
break; |
12605 |
break; |
| 12606 |
} |
12606 |
} |
| 12607 |
} |
12607 |
} |
| 12608 |
} |
12608 |
} |
| 12609 |
|
12609 |
|
| 12610 |
void ARMAsmParser::ReportNearMisses(SmallVectorImpl &NearMisses, |
12610 |
void ARMAsmParser::ReportNearMisses(SmallVectorImpl &NearMisses, |
| 12611 |
SMLoc IDLoc, OperandVector &Operands) { |
12611 |
SMLoc IDLoc, OperandVector &Operands) { |
| 12612 |
SmallVector Messages; |
12612 |
SmallVector Messages; |
| 12613 |
FilterNearMisses(NearMisses, Messages, IDLoc, Operands); |
12613 |
FilterNearMisses(NearMisses, Messages, IDLoc, Operands); |
| 12614 |
|
12614 |
|
| 12615 |
if (Messages.size() == 0) { |
12615 |
if (Messages.size() == 0) { |
| 12616 |
// No near-misses were found, so the best we can do is "invalid |
12616 |
// No near-misses were found, so the best we can do is "invalid |
| 12617 |
// instruction". |
12617 |
// instruction". |
| 12618 |
Error(IDLoc, "invalid instruction"); |
12618 |
Error(IDLoc, "invalid instruction"); |
| 12619 |
} else if (Messages.size() == 1) { |
12619 |
} else if (Messages.size() == 1) { |
| 12620 |
// One near miss was found, report it as the sole error. |
12620 |
// One near miss was found, report it as the sole error. |
| 12621 |
Error(Messages[0].Loc, Messages[0].Message); |
12621 |
Error(Messages[0].Loc, Messages[0].Message); |
| 12622 |
} else { |
12622 |
} else { |
| 12623 |
// More than one near miss, so report a generic "invalid instruction" |
12623 |
// More than one near miss, so report a generic "invalid instruction" |
| 12624 |
// error, followed by notes for each of the near-misses. |
12624 |
// error, followed by notes for each of the near-misses. |
| 12625 |
Error(IDLoc, "invalid instruction, any one of the following would fix this:"); |
12625 |
Error(IDLoc, "invalid instruction, any one of the following would fix this:"); |
| 12626 |
for (auto &M : Messages) { |
12626 |
for (auto &M : Messages) { |
| 12627 |
Note(M.Loc, M.Message); |
12627 |
Note(M.Loc, M.Message); |
| 12628 |
} |
12628 |
} |
| 12629 |
} |
12629 |
} |
| 12630 |
} |
12630 |
} |
| 12631 |
|
12631 |
|
| 12632 |
bool ARMAsmParser::enableArchExtFeature(StringRef Name, SMLoc &ExtLoc) { |
12632 |
bool ARMAsmParser::enableArchExtFeature(StringRef Name, SMLoc &ExtLoc) { |
| 12633 |
// FIXME: This structure should be moved inside ARMTargetParser |
12633 |
// FIXME: This structure should be moved inside ARMTargetParser |
| 12634 |
// when we start to table-generate them, and we can use the ARM |
12634 |
// when we start to table-generate them, and we can use the ARM |
| 12635 |
// flags below, that were generated by table-gen. |
12635 |
// flags below, that were generated by table-gen. |
| 12636 |
static const struct { |
12636 |
static const struct { |
| 12637 |
const uint64_t Kind; |
12637 |
const uint64_t Kind; |
| 12638 |
const FeatureBitset ArchCheck; |
12638 |
const FeatureBitset ArchCheck; |
| 12639 |
const FeatureBitset Features; |
12639 |
const FeatureBitset Features; |
| 12640 |
} Extensions[] = { |
12640 |
} Extensions[] = { |
| 12641 |
{ARM::AEK_CRC, {Feature_HasV8Bit}, {ARM::FeatureCRC}}, |
12641 |
{ARM::AEK_CRC, {Feature_HasV8Bit}, {ARM::FeatureCRC}}, |
| 12642 |
{ARM::AEK_AES, |
12642 |
{ARM::AEK_AES, |
| 12643 |
{Feature_HasV8Bit}, |
12643 |
{Feature_HasV8Bit}, |
| 12644 |
{ARM::FeatureAES, ARM::FeatureNEON, ARM::FeatureFPARMv8}}, |
12644 |
{ARM::FeatureAES, ARM::FeatureNEON, ARM::FeatureFPARMv8}}, |
| 12645 |
{ARM::AEK_SHA2, |
12645 |
{ARM::AEK_SHA2, |
| 12646 |
{Feature_HasV8Bit}, |
12646 |
{Feature_HasV8Bit}, |
| 12647 |
{ARM::FeatureSHA2, ARM::FeatureNEON, ARM::FeatureFPARMv8}}, |
12647 |
{ARM::FeatureSHA2, ARM::FeatureNEON, ARM::FeatureFPARMv8}}, |
| 12648 |
{ARM::AEK_CRYPTO, |
12648 |
{ARM::AEK_CRYPTO, |
| 12649 |
{Feature_HasV8Bit}, |
12649 |
{Feature_HasV8Bit}, |
| 12650 |
{ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8}}, |
12650 |
{ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8}}, |
| 12651 |
{ARM::AEK_FP, |
12651 |
{ARM::AEK_FP, |
| 12652 |
{Feature_HasV8Bit}, |
12652 |
{Feature_HasV8Bit}, |
| 12653 |
{ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8}}, |
12653 |
{ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8}}, |
| 12654 |
{(ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM), |
12654 |
{(ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM), |
| 12655 |
{Feature_HasV7Bit, Feature_IsNotMClassBit}, |
12655 |
{Feature_HasV7Bit, Feature_IsNotMClassBit}, |
| 12656 |
{ARM::FeatureHWDivThumb, ARM::FeatureHWDivARM}}, |
12656 |
{ARM::FeatureHWDivThumb, ARM::FeatureHWDivARM}}, |
| 12657 |
{ARM::AEK_MP, |
12657 |
{ARM::AEK_MP, |
| 12658 |
{Feature_HasV7Bit, Feature_IsNotMClassBit}, |
12658 |
{Feature_HasV7Bit, Feature_IsNotMClassBit}, |
| 12659 |
{ARM::FeatureMP}}, |
12659 |
{ARM::FeatureMP}}, |
| 12660 |
{ARM::AEK_SIMD, |
12660 |
{ARM::AEK_SIMD, |
| 12661 |
{Feature_HasV8Bit}, |
12661 |
{Feature_HasV8Bit}, |
| 12662 |
{ARM::FeatureNEON, ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8}}, |
12662 |
{ARM::FeatureNEON, ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8}}, |
| 12663 |
{ARM::AEK_SEC, {Feature_HasV6KBit}, {ARM::FeatureTrustZone}}, |
12663 |
{ARM::AEK_SEC, {Feature_HasV6KBit}, {ARM::FeatureTrustZone}}, |
| 12664 |
// FIXME: Only available in A-class, isel not predicated |
12664 |
// FIXME: Only available in A-class, isel not predicated |
| 12665 |
{ARM::AEK_VIRT, {Feature_HasV7Bit}, {ARM::FeatureVirtualization}}, |
12665 |
{ARM::AEK_VIRT, {Feature_HasV7Bit}, {ARM::FeatureVirtualization}}, |
| 12666 |
{ARM::AEK_FP16, |
12666 |
{ARM::AEK_FP16, |
| 12667 |
{Feature_HasV8_2aBit}, |
12667 |
{Feature_HasV8_2aBit}, |
| 12668 |
{ARM::FeatureFPARMv8, ARM::FeatureFullFP16}}, |
12668 |
{ARM::FeatureFPARMv8, ARM::FeatureFullFP16}}, |
| 12669 |
{ARM::AEK_RAS, {Feature_HasV8Bit}, {ARM::FeatureRAS}}, |
12669 |
{ARM::AEK_RAS, {Feature_HasV8Bit}, {ARM::FeatureRAS}}, |
| 12670 |
{ARM::AEK_LOB, {Feature_HasV8_1MMainlineBit}, {ARM::FeatureLOB}}, |
12670 |
{ARM::AEK_LOB, {Feature_HasV8_1MMainlineBit}, {ARM::FeatureLOB}}, |
| 12671 |
{ARM::AEK_PACBTI, {Feature_HasV8_1MMainlineBit}, {ARM::FeaturePACBTI}}, |
12671 |
{ARM::AEK_PACBTI, {Feature_HasV8_1MMainlineBit}, {ARM::FeaturePACBTI}}, |
| 12672 |
// FIXME: Unsupported extensions. |
12672 |
// FIXME: Unsupported extensions. |
| 12673 |
{ARM::AEK_OS, {}, {}}, |
12673 |
{ARM::AEK_OS, {}, {}}, |
| 12674 |
{ARM::AEK_IWMMXT, {}, {}}, |
12674 |
{ARM::AEK_IWMMXT, {}, {}}, |
| 12675 |
{ARM::AEK_IWMMXT2, {}, {}}, |
12675 |
{ARM::AEK_IWMMXT2, {}, {}}, |
| 12676 |
{ARM::AEK_MAVERICK, {}, {}}, |
12676 |
{ARM::AEK_MAVERICK, {}, {}}, |
| 12677 |
{ARM::AEK_XSCALE, {}, {}}, |
12677 |
{ARM::AEK_XSCALE, {}, {}}, |
| 12678 |
}; |
12678 |
}; |
| 12679 |
bool EnableFeature = true; |
12679 |
bool EnableFeature = true; |
| 12680 |
if (Name.starts_with_insensitive("no")) { |
12680 |
if (Name.starts_with_insensitive("no")) { |
| 12681 |
EnableFeature = false; |
12681 |
EnableFeature = false; |
| 12682 |
Name = Name.substr(2); |
12682 |
Name = Name.substr(2); |
| 12683 |
} |
12683 |
} |
| 12684 |
uint64_t FeatureKind = ARM::parseArchExt(Name); |
12684 |
uint64_t FeatureKind = ARM::parseArchExt(Name); |
| 12685 |
if (FeatureKind == ARM::AEK_INVALID) |
12685 |
if (FeatureKind == ARM::AEK_INVALID) |
| 12686 |
return Error(ExtLoc, "unknown architectural extension: " + Name); |
12686 |
return Error(ExtLoc, "unknown architectural extension: " + Name); |
| 12687 |
|
12687 |
|
| 12688 |
for (const auto &Extension : Extensions) { |
12688 |
for (const auto &Extension : Extensions) { |
| 12689 |
if (Extension.Kind != FeatureKind) |
12689 |
if (Extension.Kind != FeatureKind) |
| 12690 |
continue; |
12690 |
continue; |
| 12691 |
|
12691 |
|
| 12692 |
if (Extension.Features.none()) |
12692 |
if (Extension.Features.none()) |
| 12693 |
return Error(ExtLoc, "unsupported architectural extension: " + Name); |
12693 |
return Error(ExtLoc, "unsupported architectural extension: " + Name); |
| 12694 |
|
12694 |
|
| 12695 |
if ((getAvailableFeatures() & Extension.ArchCheck) != Extension.ArchCheck) |
12695 |
if ((getAvailableFeatures() & Extension.ArchCheck) != Extension.ArchCheck) |
| 12696 |
return Error(ExtLoc, "architectural extension '" + Name + |
12696 |
return Error(ExtLoc, "architectural extension '" + Name + |
| 12697 |
"' is not " |
12697 |
"' is not " |
| 12698 |
"allowed for the current base architecture"); |
12698 |
"allowed for the current base architecture"); |
| 12699 |
|
12699 |
|
| 12700 |
MCSubtargetInfo &STI = copySTI(); |
12700 |
MCSubtargetInfo &STI = copySTI(); |
| 12701 |
if (EnableFeature) { |
12701 |
if (EnableFeature) { |
| 12702 |
STI.SetFeatureBitsTransitively(Extension.Features); |
12702 |
STI.SetFeatureBitsTransitively(Extension.Features); |
| 12703 |
} else { |
12703 |
} else { |
| 12704 |
STI.ClearFeatureBitsTransitively(Extension.Features); |
12704 |
STI.ClearFeatureBitsTransitively(Extension.Features); |
| 12705 |
} |
12705 |
} |
| 12706 |
FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits()); |
12706 |
FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits()); |
| 12707 |
setAvailableFeatures(Features); |
12707 |
setAvailableFeatures(Features); |
| 12708 |
return true; |
12708 |
return true; |
| 12709 |
} |
12709 |
} |
| 12710 |
return false; |
12710 |
return false; |
| 12711 |
} |
12711 |
} |
| 12712 |
|
12712 |
|
| 12713 |
/// parseDirectiveArchExtension |
12713 |
/// parseDirectiveArchExtension |
| 12714 |
/// ::= .arch_extension [no]feature |
12714 |
/// ::= .arch_extension [no]feature |
| 12715 |
bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { |
12715 |
bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { |
| 12716 |
|
12716 |
|
| 12717 |
MCAsmParser &Parser = getParser(); |
12717 |
MCAsmParser &Parser = getParser(); |
| 12718 |
|
12718 |
|
| 12719 |
if (getLexer().isNot(AsmToken::Identifier)) |
12719 |
if (getLexer().isNot(AsmToken::Identifier)) |
| 12720 |
return Error(getLexer().getLoc(), "expected architecture extension name"); |
12720 |
return Error(getLexer().getLoc(), "expected architecture extension name"); |
| 12721 |
|
12721 |
|
| 12722 |
StringRef Name = Parser.getTok().getString(); |
12722 |
StringRef Name = Parser.getTok().getString(); |
| 12723 |
SMLoc ExtLoc = Parser.getTok().getLoc(); |
12723 |
SMLoc ExtLoc = Parser.getTok().getLoc(); |
| 12724 |
Lex(); |
12724 |
Lex(); |
| 12725 |
|
12725 |
|
| 12726 |
if (parseEOL()) |
12726 |
if (parseEOL()) |
| 12727 |
return true; |
12727 |
return true; |
| 12728 |
|
12728 |
|
| 12729 |
if (Name == "nocrypto") { |
12729 |
if (Name == "nocrypto") { |
| 12730 |
enableArchExtFeature("nosha2", ExtLoc); |
12730 |
enableArchExtFeature("nosha2", ExtLoc); |
| 12731 |
enableArchExtFeature("noaes", ExtLoc); |
12731 |
enableArchExtFeature("noaes", ExtLoc); |
| 12732 |
} |
12732 |
} |
| 12733 |
|
12733 |
|
| 12734 |
if (enableArchExtFeature(Name, ExtLoc)) |
12734 |
if (enableArchExtFeature(Name, ExtLoc)) |
| 12735 |
return false; |
12735 |
return false; |
| 12736 |
|
12736 |
|
| 12737 |
return Error(ExtLoc, "unknown architectural extension: " + Name); |
12737 |
return Error(ExtLoc, "unknown architectural extension: " + Name); |
| 12738 |
} |
12738 |
} |
| 12739 |
|
12739 |
|
| 12740 |
// Define this matcher function after the auto-generated include so we |
12740 |
// Define this matcher function after the auto-generated include so we |
| 12741 |
// have the match class enum definitions. |
12741 |
// have the match class enum definitions. |
| 12742 |
unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, |
12742 |
unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, |
| 12743 |
unsigned Kind) { |
12743 |
unsigned Kind) { |
| 12744 |
ARMOperand &Op = static_cast(AsmOp); |
12744 |
ARMOperand &Op = static_cast(AsmOp); |
| 12745 |
// If the kind is a token for a literal immediate, check if our asm |
12745 |
// If the kind is a token for a literal immediate, check if our asm |
| 12746 |
// operand matches. This is for InstAliases which have a fixed-value |
12746 |
// operand matches. This is for InstAliases which have a fixed-value |
| 12747 |
// immediate in the syntax. |
12747 |
// immediate in the syntax. |
| 12748 |
switch (Kind) { |
12748 |
switch (Kind) { |
| 12749 |
default: break; |
12749 |
default: break; |
| 12750 |
case MCK__HASH_0: |
12750 |
case MCK__HASH_0: |
| 12751 |
if (Op.isImm()) |
12751 |
if (Op.isImm()) |
| 12752 |
if (const MCConstantExpr *CE = dyn_cast(Op.getImm())) |
12752 |
if (const MCConstantExpr *CE = dyn_cast(Op.getImm())) |
| 12753 |
if (CE->getValue() == 0) |
12753 |
if (CE->getValue() == 0) |
| 12754 |
return Match_Success; |
12754 |
return Match_Success; |
| 12755 |
break; |
12755 |
break; |
| 12756 |
case MCK__HASH_8: |
12756 |
case MCK__HASH_8: |
| 12757 |
if (Op.isImm()) |
12757 |
if (Op.isImm()) |
| 12758 |
if (const MCConstantExpr *CE = dyn_cast(Op.getImm())) |
12758 |
if (const MCConstantExpr *CE = dyn_cast(Op.getImm())) |
| 12759 |
if (CE->getValue() == 8) |
12759 |
if (CE->getValue() == 8) |
| 12760 |
return Match_Success; |
12760 |
return Match_Success; |
| 12761 |
break; |
12761 |
break; |
| 12762 |
case MCK__HASH_16: |
12762 |
case MCK__HASH_16: |
| 12763 |
if (Op.isImm()) |
12763 |
if (Op.isImm()) |
| 12764 |
if (const MCConstantExpr *CE = dyn_cast(Op.getImm())) |
12764 |
if (const MCConstantExpr *CE = dyn_cast(Op.getImm())) |
| 12765 |
if (CE->getValue() == 16) |
12765 |
if (CE->getValue() == 16) |
| 12766 |
return Match_Success; |
12766 |
return Match_Success; |
| 12767 |
break; |
12767 |
break; |
| 12768 |
case MCK_ModImm: |
12768 |
case MCK_ModImm: |
| 12769 |
if (Op.isImm()) { |
12769 |
if (Op.isImm()) { |
| 12770 |
const MCExpr *SOExpr = Op.getImm(); |
12770 |
const MCExpr *SOExpr = Op.getImm(); |
| 12771 |
int64_t Value; |
12771 |
int64_t Value; |
| 12772 |
if (!SOExpr->evaluateAsAbsolute(Value)) |
12772 |
if (!SOExpr->evaluateAsAbsolute(Value)) |
| 12773 |
return Match_Success; |
12773 |
return Match_Success; |
| 12774 |
assert((Value >= std::numeric_limits::min() && |
12774 |
assert((Value >= std::numeric_limits::min() && |
| 12775 |
Value <= std::numeric_limits::max()) && |
12775 |
Value <= std::numeric_limits::max()) && |
| 12776 |
"expression value must be representable in 32 bits"); |
12776 |
"expression value must be representable in 32 bits"); |
| 12777 |
} |
12777 |
} |
| 12778 |
break; |
12778 |
break; |
| 12779 |
case MCK_rGPR: |
12779 |
case MCK_rGPR: |
| 12780 |
if (hasV8Ops() && Op.isReg() && Op.getReg() == ARM::SP) |
12780 |
if (hasV8Ops() && Op.isReg() && Op.getReg() == ARM::SP) |
| 12781 |
return Match_Success; |
12781 |
return Match_Success; |
| 12782 |
return Match_rGPR; |
12782 |
return Match_rGPR; |
| 12783 |
case MCK_GPRPair: |
12783 |
case MCK_GPRPair: |
| 12784 |
if (Op.isReg() && |
12784 |
if (Op.isReg() && |
| 12785 |
MRI->getRegClass(ARM::GPRRegClassID).contains(Op.getReg())) |
12785 |
MRI->getRegClass(ARM::GPRRegClassID).contains(Op.getReg())) |
| 12786 |
return Match_Success; |
12786 |
return Match_Success; |
| 12787 |
break; |
12787 |
break; |
| 12788 |
} |
12788 |
} |
| 12789 |
return Match_InvalidOperand; |
12789 |
return Match_InvalidOperand; |
| 12790 |
} |
12790 |
} |
| 12791 |
|
12791 |
|
| 12792 |
bool ARMAsmParser::isMnemonicVPTPredicable(StringRef Mnemonic, |
12792 |
bool ARMAsmParser::isMnemonicVPTPredicable(StringRef Mnemonic, |
| 12793 |
StringRef ExtraToken) { |
12793 |
StringRef ExtraToken) { |
| 12794 |
if (!hasMVE()) |
12794 |
if (!hasMVE()) |
| 12795 |
return false; |
12795 |
return false; |
| 12796 |
|
12796 |
|
| 12797 |
if (MS.isVPTPredicableCDEInstr(Mnemonic) || |
12797 |
if (MS.isVPTPredicableCDEInstr(Mnemonic) || |
| 12798 |
(Mnemonic.startswith("vldrh") && Mnemonic != "vldrhi") || |
12798 |
(Mnemonic.startswith("vldrh") && Mnemonic != "vldrhi") || |
| 12799 |
(Mnemonic.startswith("vmov") && |
12799 |
(Mnemonic.startswith("vmov") && |
| 12800 |
!(ExtraToken == ".f16" || ExtraToken == ".32" || ExtraToken == ".16" || |
12800 |
!(ExtraToken == ".f16" || ExtraToken == ".32" || ExtraToken == ".16" || |
| 12801 |
ExtraToken == ".8")) || |
12801 |
ExtraToken == ".8")) || |
| 12802 |
(Mnemonic.startswith("vrint") && Mnemonic != "vrintr") || |
12802 |
(Mnemonic.startswith("vrint") && Mnemonic != "vrintr") || |
| 12803 |
(Mnemonic.startswith("vstrh") && Mnemonic != "vstrhi")) |
12803 |
(Mnemonic.startswith("vstrh") && Mnemonic != "vstrhi")) |
| 12804 |
return true; |
12804 |
return true; |
| 12805 |
|
12805 |
|
| 12806 |
const char *predicable_prefixes[] = { |
12806 |
const char *predicable_prefixes[] = { |
| 12807 |
"vabav", "vabd", "vabs", "vadc", "vadd", |
12807 |
"vabav", "vabd", "vabs", "vadc", "vadd", |
| 12808 |
"vaddlv", "vaddv", "vand", "vbic", "vbrsr", |
12808 |
"vaddlv", "vaddv", "vand", "vbic", "vbrsr", |
| 12809 |
"vcadd", "vcls", "vclz", "vcmla", "vcmp", |
12809 |
"vcadd", "vcls", "vclz", "vcmla", "vcmp", |
| 12810 |
"vcmul", "vctp", "vcvt", "vddup", "vdup", |
12810 |
"vcmul", "vctp", "vcvt", "vddup", "vdup", |
| 12811 |
"vdwdup", "veor", "vfma", "vfmas", "vfms", |
12811 |
"vdwdup", "veor", "vfma", "vfmas", "vfms", |
| 12812 |
"vhadd", "vhcadd", "vhsub", "vidup", "viwdup", |
12812 |
"vhadd", "vhcadd", "vhsub", "vidup", "viwdup", |
| 12813 |
"vldrb", "vldrd", "vldrw", "vmax", "vmaxa", |
12813 |
"vldrb", "vldrd", "vldrw", "vmax", "vmaxa", |
| 12814 |
"vmaxav", "vmaxnm", "vmaxnma", "vmaxnmav", "vmaxnmv", |
12814 |
"vmaxav", "vmaxnm", "vmaxnma", "vmaxnmav", "vmaxnmv", |
| 12815 |
"vmaxv", "vmin", "vminav", "vminnm", "vminnmav", |
12815 |
"vmaxv", "vmin", "vminav", "vminnm", "vminnmav", |
| 12816 |
"vminnmv", "vminv", "vmla", "vmladav", "vmlaldav", |
12816 |
"vminnmv", "vminv", "vmla", "vmladav", "vmlaldav", |
| 12817 |
"vmlalv", "vmlas", "vmlav", "vmlsdav", "vmlsldav", |
12817 |
"vmlalv", "vmlas", "vmlav", "vmlsdav", "vmlsldav", |
| 12818 |
"vmovlb", "vmovlt", "vmovnb", "vmovnt", "vmul", |
12818 |
"vmovlb", "vmovlt", "vmovnb", "vmovnt", "vmul", |
| 12819 |
"vmvn", "vneg", "vorn", "vorr", "vpnot", |
12819 |
"vmvn", "vneg", "vorn", "vorr", "vpnot", |
| 12820 |
"vpsel", "vqabs", "vqadd", "vqdmladh", "vqdmlah", |
12820 |
"vpsel", "vqabs", "vqadd", "vqdmladh", "vqdmlah", |
| 12821 |
"vqdmlash", "vqdmlsdh", "vqdmulh", "vqdmull", "vqmovn", |
12821 |
"vqdmlash", "vqdmlsdh", "vqdmulh", "vqdmull", "vqmovn", |
| 12822 |
"vqmovun", "vqneg", "vqrdmladh", "vqrdmlah", "vqrdmlash", |
12822 |
"vqmovun", "vqneg", "vqrdmladh", "vqrdmlah", "vqrdmlash", |
| 12823 |
"vqrdmlsdh", "vqrdmulh", "vqrshl", "vqrshrn", "vqrshrun", |
12823 |
"vqrdmlsdh", "vqrdmulh", "vqrshl", "vqrshrn", "vqrshrun", |
| 12824 |
"vqshl", "vqshrn", "vqshrun", "vqsub", "vrev16", |
12824 |
"vqshl", "vqshrn", "vqshrun", "vqsub", "vrev16", |
| 12825 |
"vrev32", "vrev64", "vrhadd", "vrmlaldavh", "vrmlalvh", |
12825 |
"vrev32", "vrev64", "vrhadd", "vrmlaldavh", "vrmlalvh", |
| 12826 |
"vrmlsldavh", "vrmulh", "vrshl", "vrshr", "vrshrn", |
12826 |
"vrmlsldavh", "vrmulh", "vrshl", "vrshr", "vrshrn", |
| 12827 |
"vsbc", "vshl", "vshlc", "vshll", "vshr", |
12827 |
"vsbc", "vshl", "vshlc", "vshll", "vshr", |
| 12828 |
"vshrn", "vsli", "vsri", "vstrb", "vstrd", |
12828 |
"vshrn", "vsli", "vsri", "vstrb", "vstrd", |
| 12829 |
"vstrw", "vsub"}; |
12829 |
"vstrw", "vsub"}; |
| 12830 |
|
12830 |
|
| 12831 |
return std::any_of( |
12831 |
return std::any_of( |
| 12832 |
std::begin(predicable_prefixes), std::end(predicable_prefixes), |
12832 |
std::begin(predicable_prefixes), std::end(predicable_prefixes), |
| 12833 |
[&Mnemonic](const char *prefix) { return Mnemonic.startswith(prefix); }); |
12833 |
[&Mnemonic](const char *prefix) { return Mnemonic.startswith(prefix); }); |
| 12834 |
} |
12834 |
} |
| 12835 |
|
12835 |
|